claude-code - 💡(How to fix) Fix Harness writes synthetic "No response requested." turns when API returns empty content on auto-resume [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#53260Fetched 2026-04-26 05:20:16
View on GitHub
Comments
0
Participants
1
Timeline
4
Reactions
0
Participants
Timeline (top)
labeled ×4

Claude Code writes synthetic assistant-turn records to the transcript JSONL with the literal text No response requested. when an API call for that turn returns a zero-content response. The UI displays the synthetic record as if the model produced it, making the model appear stuck. Continuing the session sometimes causes subsequent real turns to echo the stub back, compounding the appearance of a stall.

Error Message

  1. When the API returns empty content, why does the harness write a synthetic stub instead of retrying with backoff or surfacing the error to the user? Reported hours of lost work per session for long skill invocations (writing-plans, foundation-research). No actionable error surfaced — the user sees only a model that appears to have given up.

Root Cause

  1. Is empty stop_sequence: "" ever actually passed to the API? If so, that's the root cause.
  2. When the API returns empty content, why does the harness write a synthetic stub instead of retrying with backoff or surfacing the error to the user?
  3. Could the auto-resume prompt include enough context that an empty response is less likely (e.g. the last assistant tool-use, or a recap of the in-progress task)?

Fix Action

Fix / Workaround

Workarounds users have to apply

Code Example

{
  "type": "assistant",
  "message": {
    "role": "assistant",
    "model": "<synthetic>",
    "stop_reason": "stop_sequence",
    "stop_sequence": "",
    "content": "No response requested."
  }
}

---

import json, os
for root, _, files in os.walk(os.path.expanduser("~/.claude/projects")):
    for f in files:
        if not f.endswith(".jsonl"): continue
        with open(os.path.join(root, f), "r", encoding="utf-8") as fh:
            for i, line in enumerate(fh, 1):
                try: obj = json.loads(line)
                except: continue
                msg = obj.get("message", {})
                if isinstance(msg, dict) and msg.get("model") == "<synthetic>":
                    print(f"{f}:{i}", msg.get("content"))
RAW_BUFFERClick to expand / collapse

Summary

Claude Code writes synthetic assistant-turn records to the transcript JSONL with the literal text No response requested. when an API call for that turn returns a zero-content response. The UI displays the synthetic record as if the model produced it, making the model appear stuck. Continuing the session sometimes causes subsequent real turns to echo the stub back, compounding the appearance of a stall.

Transcript record shape

{
  "type": "assistant",
  "message": {
    "role": "assistant",
    "model": "<synthetic>",
    "stop_reason": "stop_sequence",
    "stop_sequence": "",
    "content": "No response requested."
  }
}

model: "<synthetic>" indicates the harness wrote the record without a real API exchange. The stop_sequence: "" is suspicious — if that empty string is actually passed to the API as a stop sequence, it would match at position 0 of any response and force immediate zero-token termination.

Trigger pattern

15 stubs across one user's transcripts on this machine. Distribution by what immediately precedes the synthetic record:

Preceding eventCount
User turn11
queue-operation4

100% of the user-preceded stubs are preceded by exactly the same user turn: Continue from where you left off. — the harness's auto-resume prompt, not user-typed. The queue-operation cases are the same pattern after dequeuing batched user messages.

So the trigger is: long-running tool/skill call completes (or session resumes) → harness injects auto-resume → API returns empty → harness stubs No response requested.

Reproducibility

Hits across short and long sessions (106 lines to 1298 lines). Not strictly correlated with context length, though large system-prompt surface (cowork plugin enabled, ~80 skills + ~250 deferred MCP tools loaded) seems to make it more frequent.

Diagnostic recipe

Search any user's transcripts to confirm:

import json, os
for root, _, files in os.walk(os.path.expanduser("~/.claude/projects")):
    for f in files:
        if not f.endswith(".jsonl"): continue
        with open(os.path.join(root, f), "r", encoding="utf-8") as fh:
            for i, line in enumerate(fh, 1):
                try: obj = json.loads(line)
                except: continue
                msg = obj.get("message", {})
                if isinstance(msg, dict) and msg.get("model") == "<synthetic>":
                    print(f"{f}:{i}", msg.get("content"))

Questions for the team

  1. Is empty stop_sequence: "" ever actually passed to the API? If so, that's the root cause.
  2. When the API returns empty content, why does the harness write a synthetic stub instead of retrying with backoff or surfacing the error to the user?
  3. Could the auto-resume prompt include enough context that an empty response is less likely (e.g. the last assistant tool-use, or a recap of the in-progress task)?

Environment

  • Claude Code on Windows 11 (PowerShell + Git Bash)
  • Opus 4.7 (1M context)
  • Large skill/MCP surface (cowork plugin)

Impact

Reported hours of lost work per session for long skill invocations (writing-plans, foundation-research). No actionable error surfaced — the user sees only a model that appears to have given up.

Workarounds users have to apply

  • Avoid queueing messages while a skill runs
  • Manually retype the prompt when the stub appears (don't let it stay in history)
  • Start fresh sessions if the stub appears more than once in a row

extent analysis

TL;DR

The issue can be mitigated by modifying the harness to handle empty API responses without writing synthetic records or by adjusting the auto-resume prompt to include more context.

Guidance

  • Investigate if an empty stop_sequence is passed to the API and its implications on the response.
  • Consider implementing a retry mechanism with backoff when the API returns empty content instead of writing a synthetic stub.
  • Enhance the auto-resume prompt to include relevant context, such as the last assistant tool-use or a recap of the in-progress task, to reduce the likelihood of empty responses.

Example

No code snippet is provided as the issue requires a deeper understanding of the API and harness behavior.

Notes

The provided diagnostic recipe can help identify instances of the issue, but resolving it may require changes to the harness or API interaction. The large skill/MCP surface and cowork plugin may contribute to the frequency of the issue.

Recommendation

Apply a workaround by modifying the auto-resume prompt to include more context, as this seems to be a contributing factor to the empty API responses. This approach may help reduce the occurrence of the issue without requiring significant changes to the harness or API.

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

claude-code - 💡(How to fix) Fix Harness writes synthetic "No response requested." turns when API returns empty content on auto-resume [1 participants]