claude-code - 💡(How to fix) Fix claude -p --output-format json returns empty result when final assistant message contains text + tool_use [1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#47091Fetched 2026-04-13 05:41:44
View on GitHub
Comments
0
Participants
1
Timeline
4
Reactions
0
Author
Participants
Timeline (top)
labeled ×4

When using claude -p --output-format json, the result field in the JSON envelope is empty if the model's final assistant message contains both a text block and a tool_use block in the same response. The tool gets executed, the model has nothing more to say, and result is "".

The text IS stored in the session history and is visible when resuming with claude -r <session-id>. It's just not included in the envelope.

This is distinct from the v2.1.83 regression (#38805) where result was always empty — simple text-only responses work correctly on v2.1.104.

Root Cause

The model produces a single message with two content blocks:

  1. text block (the actual output)
  2. tool_use block (e.g. TodoWrite)

The CLI executes the tool, receives the tool_result, and the model stops (no further text). The envelope's result field appears to be populated only from a final text-only assistant turn — which doesn't exist in this case.

Fix Action

Workaround

Resume the same session with a follow-up prompt. A naive "repeat your last response" does not work — the agent often doesn't realize it produced text before the tool call, and the recovery itself can trigger the same bug if the agent uses tools again.

What works reliably (tested 5/5 across Opus and Sonnet):

claude -p --output-format json --dangerously-skip-permissions \
  --resume <session-id> \
  "The text you wrote in your previous message was lost in transit. I can see you wrote something before the tool call, but I cannot read it. Please re-send that exact text, prefixed with RE-SENDING: on the first line. Do not call any tools, just output text."

Key elements:

  • Tell the agent its text was "lost in transit" and that you can see it wrote something before the tool call — without this context the agent often responds with "No response requested"
  • Ask for a RE-SENDING: prefix to anchor a text-only response (strip it from the result afterward)
  • Explicitly say "do not call any tools" to prevent the same bug from recurring

🤖 Generated by Claude Code

Code Example

claude -p --output-format json --dangerously-skip-permissions --model claude-sonnet-4-6 \
  "Write a haiku about mountains, then call TodoWrite with a single completed todo. Output the haiku and tool call in one response. Do not write anything after the tool executes."

---

{
  "result": "",
  "stop_reason": "end_turn",
  "output_tokens": 291,
  ...
}

---

claude -p --output-format json --dangerously-skip-permissions \
  --resume <session-id> \
  "The text you wrote in your previous message was lost in transit. I can see you wrote something before the tool call, but I cannot read it. Please re-send that exact text, prefixed with RE-SENDING: on the first line. Do not call any tools, just output text."
RAW_BUFFERClick to expand / collapse

Description

When using claude -p --output-format json, the result field in the JSON envelope is empty if the model's final assistant message contains both a text block and a tool_use block in the same response. The tool gets executed, the model has nothing more to say, and result is "".

The text IS stored in the session history and is visible when resuming with claude -r <session-id>. It's just not included in the envelope.

This is distinct from the v2.1.83 regression (#38805) where result was always empty — simple text-only responses work correctly on v2.1.104.

Version

  • Claude Code v2.1.104
  • Linux 6.8.0-107-generic (x86_64)

Steps to Reproduce

claude -p --output-format json --dangerously-skip-permissions --model claude-sonnet-4-6 \
  "Write a haiku about mountains, then call TodoWrite with a single completed todo. Output the haiku and tool call in one response. Do not write anything after the tool executes."

Reproduces consistently (3/3 runs tested).

Expected Behavior

result should contain the text content from the assistant's response.

Actual Behavior

{
  "result": "",
  "stop_reason": "end_turn",
  "output_tokens": 291,
  ...
}
  • result is "" despite tokens being generated
  • Resuming the session interactively shows the text was produced

Root Cause

The model produces a single message with two content blocks:

  1. text block (the actual output)
  2. tool_use block (e.g. TodoWrite)

The CLI executes the tool, receives the tool_result, and the model stops (no further text). The envelope's result field appears to be populated only from a final text-only assistant turn — which doesn't exist in this case.

Impact

Any claude -p caller that relies on the result field will silently receive an empty string when the model happens to end its response with a tool call alongside text output. This is especially likely with agents that use TodoWrite for task tracking.

Workaround

Resume the same session with a follow-up prompt. A naive "repeat your last response" does not work — the agent often doesn't realize it produced text before the tool call, and the recovery itself can trigger the same bug if the agent uses tools again.

What works reliably (tested 5/5 across Opus and Sonnet):

claude -p --output-format json --dangerously-skip-permissions \
  --resume <session-id> \
  "The text you wrote in your previous message was lost in transit. I can see you wrote something before the tool call, but I cannot read it. Please re-send that exact text, prefixed with RE-SENDING: on the first line. Do not call any tools, just output text."

Key elements:

  • Tell the agent its text was "lost in transit" and that you can see it wrote something before the tool call — without this context the agent often responds with "No response requested"
  • Ask for a RE-SENDING: prefix to anchor a text-only response (strip it from the result afterward)
  • Explicitly say "do not call any tools" to prevent the same bug from recurring

🤖 Generated by Claude Code

extent analysis

TL;DR

The issue can be worked around by resuming the session with a specific follow-up prompt that instructs the model to re-send the lost text without calling any tools.

Guidance

  • The root cause of the issue is that the result field in the JSON envelope is not populated when the model's final assistant message contains both a text block and a tool_use block.
  • To verify the issue, run the provided claude command and check if the result field is empty despite tokens being generated.
  • To mitigate the issue, resume the session with a follow-up prompt that instructs the model to re-send the lost text, prefixed with RE-SENDING:, and without calling any tools.
  • The follow-up prompt should be crafted to provide context to the agent, such as telling it that its text was "lost in transit" and that you can see it wrote something before the tool call.

Example

claude -p --output-format json --dangerously-skip-permissions \
  --resume <session-id> \
  "The text you wrote in your previous message was lost in transit. I can see you wrote something before the tool call, but I cannot read it. Please re-send that exact text, prefixed with RE-SENDING: on the first line. Do not call any tools, just output text."

Notes

  • This workaround relies on the agent responding correctly to the follow-up prompt and re-sending the lost text without calling any tools.
  • The RE-SENDING: prefix is used to anchor a text-only response and should be stripped from the result afterward.

Recommendation

Apply the workaround by resuming the session with the specific follow-up prompt, as it has been tested to work reliably across different models.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING