claude -p exits with stop_reason: tool_use and empty result mid-generation (stream interruption treated as success)

Status Fixed / completed
Reported on v2.1.85
Maintainer reply ✓ Yes — ashwin-ant
Activity 5 comments · opened Mar 29, 2026 · closed Apr 18, 2026
💡 Likely answer: A maintainer (ashwin-ant, collaborator) responded on this thread — see the highlighted reply below.

Description

When running claude -p in non-interactive/headless mode, the CLI can exit cleanly (subtype: "success", is_error: false, exit code 0) with stop_reason: "tool_use" and an empty result: "", even though the model was mid-generation and had not completed its task.

This is problematic for automation because the caller has no way to distinguish "agent finished successfully with no output" from "agent was interrupted mid-work."

Reproduction

Command:

claude --dangerously-skip-permissions --model sonnet -p --output-format stream-json --verbose "<prompt>"

Version: 2.1.85

Environment: GitHub Actions runner (Ubuntu 24.04), running as part of a CI automation pipeline.

Context: The agent was executing a multi-step task (analyzing a PR, generating tests, editing files). After 28 turns and 251 seconds, the agent had successfully generated test files and was starting a new sub-task (UI testing) when the session ended.

Observed Behavior

The final NDJSON result event:

{
  "type": "result",
  "subtype": "success",
  "is_error": false,
  "duration_ms": 251016,
  "num_turns": 28,
  "result": "",
  "stop_reason": "tool_use",
  "total_cost_usd": 0.895
}

The last assistant message before the result event was a thinking block with only 8 output tokens and stop_reason: null (streaming partial):

{
  "type": "assistant",
  "message": {
    "content": [
      {
        "type": "thinking",
        "thinking": "Let me try to navigate to the frontend app URL (http://localhost:5173) to attempt the UI test."
      }
    ],
    "stop_reason": null,
    "usage": { "output_tokens": 8 }
  }
}

The model was clearly mid-generation (emitted a thinking block but never produced the subsequent tool_use block). The API stream appears to have been interrupted, and Claude Code treated this as a successful completion.

Expected Behavior

One of the following:

  1. Retry the API call when a streaming response ends without a terminal stop_reason (end_turn, max_tokens, or stop_sequence)
  2. Report this as an error (e.g., subtype: "error_stream_interrupted") so callers can distinguish it from a genuine success
  3. At minimum, do not report subtype: "success" when result is empty and stop_reason is "tool_use" — this combination means the agent wanted to continue but was stopped

What This Is NOT

Ruled out through analysis of the NDJSON log (84 entries, 28 turns):

| Hypothesis | Evidence Against |
|---|---|
| --max-turns limit | Not passed; would produce subtype: "error_max_turns" |
| --max-budget-usd | Not set; would produce subtype: "error_max_budget_usd" |
| External timeout (SIGTERM) | Result event is present and complete; process exited cleanly |
| Context window exhaustion | ~80k / 200k tokens used (40%) |
| Output token limit | 14.7k / 32k total; only 8 tokens in last turn |
| Permission denial | permission_denials: [] |

Impact

In our CI automation, result: "" + subtype: "success" causes the pipeline to treat the run as "no tests generated" and post a skip comment to the PR — even though the agent had already generated test files and made 4 edits. The $0.90 of API spend is wasted, and the PR author sees incorrect "No Tests Generated" output.

Additional Context

  • The agent made 27 successful tool calls before this happened (MCP tools, file reads, edits, glob searches)
  • The last successful tool was a ToolSearch that returned a tool reference — the model received it and started thinking about what to do with it
  • No errors, warnings, or anomalies appear anywhere in the 84-line NDJSON log
  • The duration_api_ms (250281) is very close to duration_ms (251016), suggesting no significant non-API time

View original on GitHub ↗

5 Comments

github-actions[bot] · 6 months ago

Found 2 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/38905
  2. https://github.com/anthropics/claude-code/issues/40240

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

yurukusa · 6 months ago

/tmp/issue-40432-comment.md

ashwin-ant collaborator · 6 months ago

This was fixed in v2.1.105 — claude -p now retries once and then surfaces an error when a stream is interrupted mid-generation, instead of exiting silently with an empty result. If you're still seeing this in the latest version, please comment with your version and repro and we'll reopen.

archit · 5 months ago

@ashwin-ant out of curiosity, what sort of errors were being silently ignored ?

github-actions[bot] · 5 months ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.