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
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_binding → local |
| 08-27 16:39:38 | Parent session session_0730c2bd resumed via ACP → runtime.set_binding → acp: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
- 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. - 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 withinternaland 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 asfailedwith codeinternal,retryable: false. - The user cannot recover from within the session: scheduled cron jobs cannot even be deleted (
CronDeletealso 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)
- Open/resume session A through an ACP client (web UI / IDE) so its binding becomes
acp:session_A. - Fork session A → session B (
/forkor fork from the client). - Use session B — everything works while session A's runtime is registered.
- Close session A (or otherwise let its ACP runtime unregister), e.g. reload the web UI.
- 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 tolocal(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
localand 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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