anthropics / anthropics/claude-code
Session goes permanently idle after a tool_result is delivered, with zero pending tool calls and no compaction in progress
- Lingua principale
- Python
- Stelle
- 145k
- Fork
- 23.1k
- Metriche di merge delle PR
- Metriche PR in attesa
Descrizione
### Preflight Checklist
- [x] I have searched [existing issues](https://github.com/anthropics/claude-code/issues?q=is%3Aissue+state%3Aopen+label%3Abug) and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code (2.1.270, confirmed as the version actually running, not just the installed one)
Third distinct entry point into the same unrecoverable idle state, split out from #94252 (a `tool_result` that never arrives) and #94261 (compaction stalling at 95%). This one is the hardest of the three to detect, because **the tool result arrives normally and nothing is left pending anywhere.**
### What's Wrong?
A tool call completed, its `tool_result` was delivered and persisted, and the assistant turn that should have consumed it never ran. The session sat idle for about five minutes producing no output, accepted four further messages into its queue without consuming any of them, and only recovered when I killed the process and restarted it.
The transcript records the result arriving 2 milliseconds after the call:
```
11:26:27.165Z assistant tool_use ToolSearch
11:26:27.167Z user tool_result <- delivered
11:28:44.410Z queue-operation enqueue <- my message, never consumed
11:30:15.231Z queue-operation enqueue <- re-queued
11:30:16.415Z queue-operation enqueue <- re-queued
11:30:48.467Z queue-operation enqueue <- second message, never consumed
(process killed and restarted here)
11:31:14.804Z user "Continue from where you left off."
```
**Zero orphaned tool calls.** Diffing every `tool_use` id against every `tool_result` `tool_use_id` across the session and all of its subagent transcripts:
```
tool_use 276 / tool_result 276 / orphaned 0 at the moment of the stall
```
This is what makes it distinct from #94252, where exactly one call had no result. And unlike #94261 there was no compaction in progress: the UI showed no percentage, and the most recent compaction had **completed** successfully three minutes earlier at 11:23:29Z. The session had completed 2 compactions in total, both fine.
So the pending-work bookkeeping is clean in every direction, and the turn is still dead. Whatever schedules the continuation after a delivered `tool_result` did not run, and nothing timed out or complained.
### What Should Happen?
A delivered `tool_result` should always be followed by either the next assistant turn or a surfaced error. If the continuation cannot be scheduled, that should fail loudly rather than leaving the session idle and accepting input it will never process.
Queued messages should also not be silently retained by a session that is no longer consuming its queue. Four enqueue records accumulated with no dequeue; from the transcript alone it is not possible to tell which queued messages were ever consumed, because dequeue records carry no content.
### Error Messages/Logs
None. No error in the UI, none in the transcript, no timeout, no retry. `isApiErrorMessage` entries: 0.
### Steps to Reproduce
No deterministic repro. Reporting the conditions and the identification method, since this mode is invisible to the checks that identify the other two.
Conditions: a long analysis-heavy session (1021 transcript entries, 276 tool calls, several days of `--resume`), auto-compaction having completed minutes earlier, no unusual host load.
To identify it:
1. Confirm the process is idle rather than busy: `sample 5`, and compute the main thread's `kevent64` **sample count** as a share of that thread's total. Do not use `grep -c kevent64`, which returns 3 for wedged and healthy processes alike because the string appears once in the main thread, once in a helper thread and once in the by-function summary.
2. Diff `tool_use` ids against `tool_result` ids, including `subagents/*.jsonl`. **Zero orphans does not clear the session.** For this bug it is zero.
3. Read the transcript tail. The signature is a `tool_use` with its matching `tool_result` present, no assistant entry after it, and then `queue-operation` enqueue records with nothing consuming them.
A caution on step 2, since it cost me a false positive today: a **pending `AskUserQuestion` looks exactly like a hang** from outside. It leaves one orphaned `tool_use` and a main thread ~98% parked in `kevent64`. A healthy session waiting at the prompt also reads ~98%, so the idle stack never proves a hang by itself.
### Claude Model
`claude-opus-5`
### Is this a regression?
I don't know
### Last Working Version
(not known)
### Claude Code Version
2.1.270 (Claude Code)
### Platform
AWS Bedrock
### Operating System
macOS
### Terminal/Shell
Terminal.app (macOS)
### Additional Information
macOS 27.0 (build 26A428), Darwin 27.0.0, arm64. Runtime is Bun.
**Ruled out by testing:**
- *A dropped tool result.* 276 of 276 calls returned, verified across the session and every subagent transcript.
- *A stalled compaction.* The last compaction completed 3 minutes earlier and is present in the transcript with `isCompactSummary` and `compactMetadata`. No percentage was displayed.
- *A request in flight.* No `ESTABLISHED` socket.
- *Process death.* The process was alive and idle throughout; I killed it deliberately to recover.
- *The specific tool.* The stall followed `ToolSearch`, but that is a single observation and I would not weight it. I also chased and discarded a `SendMessage` correlation on the sibling issue: `SendMessage` is the last call in 49.5% of agents that finish normally, so dying after one is less likely than chance.
**Suggested fix direction:** the same stall detector proposed on #94261, and for the same reason -- it must not be keyed on pending work. All three failure modes reach an idle event loop with a turn in progress, but only one of them leaves a pending `tool_use` behind. A detector that asks "is a turn marked in progress while the event loop has no registered work" catches all three; anything keyed on outstanding tool calls or on compaction state catches at most one.
**Impact:** unrecoverable in place. Killing and restarting was the only option, and restarting is what makes this bug expensive rather than merely annoying: the session cannot tell you it is stuck, so the time lost is however long you wait before giving up on it.
Paths, hostnames, repository names and session ids are replaced or omitted. Timestamps, counts and percentages are unmodified.
Guida per i contributori
Nessuna guida per i contributori indicizzata per questo repository
Valutazione
Questa issue non è ancora stata valutata.