MoonshotAI / MoonshotAI/kimi-code

Forked session inherits parent's "acp:" runtime binding — every tool call fails with "runtime ... does not exist in workspace" once the parent session ends

Open
#3,311 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
7.5k
Forks
1.2k
Avg merge
11h 53m
Merged PRs (30d)
350

Description

Summary

A session that was forked from a session running on an ACP runtime keeps the parent's runtime binding (acp:<parent-session-id>) instead of getting its own. As long as the parent session's ACP runtime is alive, the fork works fine. Once the parent session ends / its ACP runtime is unregistered, every tool call in the fork fails with:

runtime acp:session_0730c2bd-1a3f-4dea-a326-64c3b98396c0 does not exist in workspace wd_eb1243_b29b0a783e63

and the turn aborts with internal — surfaced in the UI as "模型请求失败,本轮对话已中断" (model request failed, turn interrupted), which is misleading: the LLM request itself succeeds; the failure happens when resolving the runtime for tool execution.

There is no validation, rebind, or fallback to the local runtime, so the session is permanently bricked: even local-only management tools (e.g. CronDelete) cannot run, and scheduled cron tasks keep firing and failing.

Environment

  • Kimi Code CLI: 0.39.0 (wire protocol 1.5)
  • OS: Linux x64, Node.js 24.15.0
  • Client in use: Kimi web UI (ACP), session also forked twice (Fork: Fork: ...)

Timeline (from the exported wire log, all times local UTC+8)

Time Event
08-22 11:33 Session history starts; runtime.set_bindinglocal
08-27 16:39:38 Parent session session_0730c2bd resumed via ACP → runtime.set_bindingacp:session_0730c2bd-... (correct for the parent itself)
08-27 21:55:05 Session forked → new session session_0474e71d created. No runtime.set_binding is emitted after the fork — the fork silently inherits acp:session_0730c2bd-...
08-27 16:45 → 08-28 09:55 Fork keeps working normally (turns 165–202 all completed, incl. cron-fired turns every 30 min through the night), because the parent's ACP runtime is still registered in the workspace
08-28 09:57:30 Web UI reloads (app:load:complete, sessionCount=26) — parent's ACP runtime no longer exists
08-28 09:57:33 Turn 203 fails: internal / runtime acp:session_0730c2bd-... does not exist in workspace wd_...
08-28 10:01–10:02 Turns 204–206 fail identically. Turns where the model only replies with text succeed; any step containing a tool call dies with finishReason: "error"

Expected behavior

  1. Forking a session should rebind the fork to local (or to its own ACP runtime if the fork is created through an ACP client) — never keep a binding that references the parent session's runtime.
  2. If the bound runtime is gone, tool execution should detect this, fall back to local (or rebind) and/or surface an actionable error ("session bound to a runtime that no longer exists — reattach or rebind"), instead of failing every turn with internal and a misleading "model request failed" message.

Actual behavior

  • Every tool call throws RuntimeError: runtime acp:<parent-session> does not exist in workspace <ws>; the turn is aborted as failed with code internal, retryable: false.
  • The user cannot recover from within the session: scheduled cron jobs cannot even be deleted (CronDelete also goes through runtime resolution), and cron keeps firing into the broken session.
  • Pure-text replies still work, so from the user's perspective "the model answers, but goes crazy the moment it touches a tool".

Steps to reproduce (inferred from wire log)

  1. Open/resume session A through an ACP client (web UI / IDE) so its binding becomes acp:session_A.
  2. Fork session A → session B (/fork or fork from the client).
  3. Use session B — everything works while session A's runtime is registered.
  4. Close session A (or otherwise let its ACP runtime unregister), e.g. reload the web UI.
  5. In session B, send any prompt that triggers a tool call → turn fails with the error above; session is unrecoverable.

Evidence

Redacted excerpts from the session's agents/main/wire.jsonl and logs/kimi-web.jsonl (exported via the debug-zip export; workspace path redacted, otherwise verbatim):

Wire log excerpts (click to expand)

1. Initial binding — local (line 1, 2026-08-22 11:33:43):

{"type": "runtime.set_binding", "workspaceId": "wd_eb1243_b29b0a783e63", "runtimeId": "local", "agentId": "main", "time": 1787369623562}

2. Parent session resumed via ACP — binding set to acp:<parent-session-id> (line 21594, 2026-08-27 16:39:38):

{"type": "runtime.set_binding", "workspaceId": "wd_eb1243_b29b0a783e63", "runtimeId": "acp:session_0730c2bd-1a3f-4dea-a326-64c3b98396c0", "agentId": "main", "time": 1787819978190}

3. This session created by fork (line 22089, 2026-08-27 21:55:05) — and no runtime.set_binding ever after:

{"type": "forked", "agentId": "main", "time": 1787838905535}

A grep for "type": "runtime.set_binding" over the whole wire returns exactly the two events above — the fork inherited the parent's ACP binding.

4. Web UI reload ~2s before the first failure (logs/kimi-web.jsonl):

{"ts": 1787882250745, "event": "app:load:start"}
{"ts": 1787882251038, "event": "app:load:complete", "sessionId": "session_0474e71d-b859-49c9-b08c-38c12fa0ea86", "status": "accepted", "durationMs": 293, "sessionCount": 26, "workspaceCount": 14}
{"ts": 1787882251063, "event": "ws:connection", "status": "connected"}

5. All subsequent turns fail identically (lines 23937 / 23952 / 23976 / 23988):

{"type": "turn.ended", "agentId": "main", "turnId": 203, "reason": "failed", "error": {"code": "internal", "message": "runtime acp:session_0730c2bd-1a3f-4dea-a326-64c3b98396c0 does not exist in workspace wd_eb1243_b29b0a783e63", "name": "RuntimeError", "retryable": false}, "durationMs": 96558, "time": 1787882253457}
{"type": "turn.ended", "agentId": "main", "turnId": 204, "reason": "failed", "error": {"code": "internal", "message": "runtime acp:session_0730c2bd-1a3f-4dea-a326-64c3b98396c0 does not exist in workspace wd_eb1243_b29b0a783e63", "name": "RuntimeError", "retryable": false}, "durationMs": 61615, "time": 1787882466680}
{"type": "turn.ended", "agentId": "main", "turnId": 205, "reason": "failed", "error": {"code": "internal", "message": "runtime acp:session_0730c2bd-1a3f-4dea-a326-64c3b98396c0 does not exist in workspace wd_eb1243_b29b0a783e63", "name": "RuntimeError", "retryable": false}, "durationMs": 42913, "time": 1787882517681}
{"type": "turn.ended", "agentId": "main", "turnId": 206, "reason": "failed", "error": {"code": "internal", "message": "runtime acp:session_0730c2bd-1a3f-4dea-a326-64c3b98396c0 does not exist in workspace wd_eb1243_b29b0a783e63", "name": "RuntimeError", "retryable": false}, "durationMs": 14691, "time": 1787882540119}

6. The failing step dies on tool execution, not on the LLM call (line 23936, turn 203 step 1):

{"type": "step.end", "uuid": "0e81879d-897c-42b0-875d-cb11652f1126", "turnId": "203", "step": 1, "finishReason": "error"}

The LLM request for the same step completed normally (ttftMs=93411, 127 output tokens in kimi-code.log); the turn then failed at tool dispatch. In turn 205, step 1 (pure text reply) ended with end_turn and only step 2 (with a tool call) errored — confirming the failure is tied to tool execution, not the model.

7. state.json at export:

{"id":"session_0474e71d-b859-49c9-b08c-38c12fa0ea86","version":2,"cwd":"<workspace>","archived":false,"lastTurnReason":"failed","title":"Fork: Fork: 当前编译验证","forkedFrom":"session_0730c2bd-1a3f-4dea-a326-64c3b98396c0","lastPrompt":"继续"}

Note forkedFrom matches the session id embedded in the dead acp: runtime id.

The full (unredacted) debug ZIP contains internal/company data, so it is not attached here; I can provide it via code@moonshot.ai referencing this issue if needed.

Suggested fix direction

  • On fork: strip/reset any acp:* runtime binding and rebind the new session to local (or to a fresh ACP runtime registered under the new session id).
  • On tool dispatch: if the bound runtime id is not registered in the workspace, attempt rebind to local and only fail with a clear, actionable error if that is impossible.
  • Reword the user-facing message: this is not a model request failure — report the actual runtime resolution error.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Trace the fork handling and the runtime.set_binding events first, using the wire.jsonl evidence to confirm how the child retains the parent's ACP binding. Then inspect runtime resolution during tool dispatch, including CronDelete; done means a fork no longer uses the parent's runtime and a missing binding produces recovery or an actionable error instead of an internal failure.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend, cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.