Harness hangs indefinitely after Skill tool returns tool_result — no API call, no assistant event, no token usage
Summary
After invoking the Skill tool, the harness occasionally hangs for many minutes with zero visible activity — no assistant event written to the session JSONL, no usage block, no token delta. The model is never called. The only recovery is to interrupt with Esc/Ctrl+C and resend.
I first assumed these were slow extended-thinking turns, but the JSONL proves otherwise: real thinking writes an assistant event at the end with a usage block; these stalls write nothing at all between the Skill tool's tool_result event and the user's interrupt event.
Environment
- Claude Code version: 2.1.107
- Platform: darwin 25.4.0 (macOS)
- Shell: zsh
- Model: claude-opus-4-6 (1M context)
- Project location: iCloud Drive (
~/Library/Mobile Documents/com~apple~CloudDocs/...) — may or may not be relevant
Reproducer (observed)
- Start a normal Claude Code session in a project directory.
- Invoke a Skill via the
Skilltool (e.g.superpowers:writing-plans,superpowers:subagent-driven-development). The skill content is returned as atool_resultevent in the session JSONL. - Claude should now emit its next assistant turn (thinking + text + any tool calls).
- Instead: nothing happens. No assistant event. No
usagerecord. Silence for minutes until the user interrupts.
Not 100% reproducible on every Skill invocation — observed 2–3 times in a single day of heavy use. Correlation with the Skill tool is tight: every observed stall begins on the turn immediately following a Skill tool_result.
Evidence from JSONL
Two sessions from 2026-04-14, same project, analyzed by parsing the JSONL files in ~/.claude/projects/<slug>/<session>.jsonl:
| Session | Gap | BEFORE event | AFTER event | Assistant event in gap? | usage block? |
| --- | --- | --- | --- | --- | --- |
| 23a3cec3… | 40.7 min | user / tool_result — Skill returning subagent-driven-development content | user / text [Request interrupted by user] | No | No |
| 08020c86… | 8.4 min | user / tool_result — Skill returning writing-plans content | queue-operation (user's interrupt message) | No | No |
| 23a3cec3… (control) | 10.2 min | attachment | assistant with tool_use Bash | Yes | Yes (cache_read_input_tokens=364262, output_tokens=343) |
The "control" row is a legitimate slow-thinking turn in the same session — it writes a full assistant event with a usage block at the end. The two stall rows have zero events between the Skill tool_result and the interrupt, proving the model was never invoked.
Expected behavior
After a Skill tool_result arrives, the harness should send the conversation to the API within seconds, and either:
- produce an
assistantevent with ausageblock (possibly many seconds later for long thinks), or - fail visibly with an error event.
Actual behavior
The harness enters a state where no API request is made (no assistant event, no token usage) and remains there indefinitely until the user interrupts. After interrupt + retry, the same turn completes normally in seconds.
Impact
From the user's side it is indistinguishable from a hang. We lost 40+ minutes in a single instance and had to interrupt and resend. The UI status bar shows a token counter that never ticks, which is the giveaway — but it's easy to mistake for "Claude is thinking very hard."
Diagnostic suggestions
- Log the exact point between "Skill
tool_resultwritten to JSONL" and "request dispatched to API" — is the request being constructed? Submitted? Waiting on a lock? - Check whether skill content of certain sizes (the two observed stalls were triggered by skills with ~300–600 line markdown bodies) crosses a buffer/chunking threshold.
- Add a client-side timeout + error event when a turn has been in "awaiting assistant response" state for > N seconds with no network activity, so users can tell hang from think.
Happy to share the full JSONL files privately if useful — they contain project context so I'd rather not attach publicly.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗