Skip to content

web: transcript baseline GET times out at 30s on large live sessions (200 + parse phase), session renders empty and retries forever #3881

Description

@REtoolsx

What version of Kimi Code is running?

2.0.0 (kimi --version). First seen on 0.42.0; reproduced unchanged on 2.0.0. The analysis below is against main @ 1fddc16e3.

Which open platform/subscription were you using?

Moonshot AI open platform (api.moonshot.ai)

Which model were you using?

kimi-k3 (moonshot-ai/kimi-k3)

What platform is your computer?

Microsoft Windows NT 10.0.26200.0 x64 (Windows 11 Home)

What issue are you seeing?

In kimi web, some sessions never render their content. Opening the session shows nothing from the transcript and the UI falls back to the "new session" view, even though the agent is clearly still running (the working/loading indicator keeps animating). So I cannot see anything the agent is doing in that session.

The browser console logs this on every retry (attempt counter keeps climbing, this one is attempt 15):

[kimi-code] transcript baseline retry failed
Object { sessionId: "session_xxxxx", attempt: 15, err: DaemonNetworkError }

err: DaemonNetworkError: Failed to parse JSON response from GET /sessions/session_xxxxx/transcript

Full error object:

{
  "sessionId": "session_xxxxx",
  "attempt": 15,
  "err": {
    "cause": {},
    "method": "GET",
    "path": "/sessions/session_xxxxx/transcript",
    "url": "http://xxxx/api/v1/sessions/session_xxxxx/transcript?agent_id=main&page_size=10",
    "requestId": "xxxxxx",
    "phase": "parse",
    "timeoutMs": 30000,
    "status": 200,
    "statusText": "OK",
    "contentType": "application/json; charset=utf-8",
    "timestamp": 179966783,
    "durationMs": 30000,
    "name": "DaemonNetworkError"
  }
}

Note the combination: status: 200, contentType: application/json, phase: "parse", durationMs: 30000 == timeoutMs, and an empty cause. The server did answer with 200, but the client gave up exactly at the 30 s budget while reading/parsing the body, so this is not a "server is down" case.

What steps can reproduce the bug?

  1. Start kimi web and open the UI in the browser.
  2. Have a long-running / large session (in my case the agent works for a long time and produces a lot of tool output). The session is still actively running when I open it.
  3. Open that session from the sidebar (or reload the tab while on it).
  4. Nothing from the transcript is rendered; the UI shows the "new session" area, while the working indicator shows the agent is still busy.
  5. Console shows the transcript baseline retry failed error above, and it keeps retrying forever with the same failure (attempt increases; I have seen 15+).

Other, smaller sessions in the same server open fine. Session id available on request (redacted above as session_xxxxx).

What is the expected behavior?

The session transcript should load (at least the requested page of 10 turns) and I should be able to follow what the agent is doing. If the first page cannot be loaded within the timeout, the UI should say so explicitly and keep the session context (not silently fall back to the new-session view), and the retries should have a chance of succeeding rather than hitting the same wall every time.

Additional information

I looked at the code in this repo (main @ 1fddc16e3) and the shipped web bundle (apps/kimi-code/dist-web/assets/index-DusVyqlT.js) to narrow it down:

  • Client side, single 30 s budget for headers + body. The generic REST request() in the web bundle creates one AbortSignal with timeoutMs = 30000 and passes it to fetch(). The same signal is still live while it does await response.text() followed by JSON.parse(...). If the body has not been fully received within 30 s from the start of the request, the abort fires inside text(), and the resulting AbortError is wrapped as phase: "parse" / Failed to parse JSON response. That matches every field in the error above (status 200, durationMs === timeoutMs, cause: {} because DOMException serializes to an empty object).
  • Server side, page_size only bounds items. GET /sessions/{session_id}/transcript (packages/kap-server/src/routes/transcript.ts) paginates the turns, but for a live session it also serializes the full, unpaginated tasks, interactions, attachments, todos, prompts, meta and agents collections in the same envelope. The 10 turns themselves can also carry very large tool outputs. For a big session the body is therefore large regardless of page_size=10. There is no response compression in kap-server either. Before responding, the live path also awaits whenReady() and ensureAgentHistory() (wire-record backfill), which is time spent inside the same 30 s budget.
  • Retry loop cannot recover. The transcript pool retries the baseline load with min(attempt * 2000, 15000) ms backoff, indefinitely. Only the first failure is surfaced (onBaselineErrorpushOperationFailure("loadSessionTranscript")); later ones only log transcript baseline retry failed. Every retry issues exactly the same request with the same 30 s cap, so once the response is too big/slow to fit, it fails forever and the UI stays empty.

Possibly related:

Ideas that would address it (happy to test a build):

  • Use a separate, longer read timeout for the transcript baseline (or an idle timeout on body progress) instead of one total 30 s budget for the whole request.
  • Bound the non-items collections in the transcript response (paginate / lazy-load interactions, attachments, prompts, …) so page_size actually bounds the payload; or enable compression for /api/v1 JSON responses.
  • On repeated baseline failure, keep the session view with an explicit error/retry instead of the new-session fallback, and make the retry loop stop or back off further after N attempts.

Contribution

  • I am willing to submit a PR for this bug fix myself (please wait for maintainer approval in this issue first)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions