Problem
Fix the Claude harness's post-denial retry path first — a permission_denied on a compound Bash command is immediately followed, on the very next turn, by the Anthropic API rejecting the request body as invalid JSON, burning the run's last retry and failing the whole job.
Affected workflows and runs
- Claude Code User Documentation Review (
.github/workflows/claude-code-user-docs-review.lock.yml) — §31388621726, 2026-08-10T12:33Z. First failure in the last 8 daily runs; all 7 prior runs succeeded.
Probable root cause
Sequence from the log, all within attempt 4/4 (the last retry):
- Agent calls
Bash with a compound command (mkdir -p ... ; ls ... ; find ...).
- Rejected:
"subtype":"permission_denied", "decision_reason_type":"subcommandResults" — "contains multiple operations."
- On the very next turn:
"text":"API Error: 400 The request body is not valid JSON: unexpected character: line 1 column 1 (char 0)".
The harness's own retry-classifier logs isOverloadedError=false isRateLimitError=false isAuthenticationFailedError=false ... permissionDeniedCount=0 — it doesn't even recognize the permission denial happened, and has no bucket for this 400. That strongly suggests the CLI re-serializes the conversation (including the permission_denied tool-result) into the next API request incorrectly, producing an empty or malformed body, which the Anthropic API then rejects at the transport level before any model logic runs. Because this consumes the final retry, the job has nothing left and fails outright.
Proposed remediation
- Reproduce: force a
permission_denied on a multi-part Bash command mid-session, then continue the turn, and capture the exact outgoing request body to confirm it's empty/malformed JSON.
- Fix the message-serialization path so a
permission_denied tool result never produces a non-JSON/empty body on the following turn.
- Teach the harness's failure classifier to recognize "API Error: 400 ... not valid JSON" as a retryable transport-level bug (distinct from a real 400 from the model), and/or grant one extra attempt specifically for this signature so a single serialization glitch doesn't consume the whole retry budget.
Success criteria
- Forcing a
permission_denied on a compound Bash command no longer produces a 400 invalid JSON error on the following turn.
- Next 3 scheduled runs of Claude Code User Documentation Review complete without this signature.
Generated by 🔍 [aw] Failure Investigator (6h) · agent · 176.3 AIC · ⌖ 43.7 AIC · ⊞ 5.3K · ◷
Problem
Fix the Claude harness's post-denial retry path first — a
permission_deniedon a compound Bash command is immediately followed, on the very next turn, by the Anthropic API rejecting the request body as invalid JSON, burning the run's last retry and failing the whole job.Affected workflows and runs
.github/workflows/claude-code-user-docs-review.lock.yml) — §31388621726, 2026-08-10T12:33Z. First failure in the last 8 daily runs; all 7 prior runs succeeded.Probable root cause
Sequence from the log, all within attempt 4/4 (the last retry):
Bashwith a compound command (mkdir -p ... ; ls ... ; find ...)."subtype":"permission_denied", "decision_reason_type":"subcommandResults"— "contains multiple operations.""text":"API Error: 400 The request body is not valid JSON: unexpected character: line 1 column 1 (char 0)".The harness's own retry-classifier logs
isOverloadedError=false isRateLimitError=false isAuthenticationFailedError=false ... permissionDeniedCount=0— it doesn't even recognize the permission denial happened, and has no bucket for this 400. That strongly suggests the CLI re-serializes the conversation (including thepermission_deniedtool-result) into the next API request incorrectly, producing an empty or malformed body, which the Anthropic API then rejects at the transport level before any model logic runs. Because this consumes the final retry, the job has nothing left and fails outright.Proposed remediation
permission_deniedon a multi-part Bash command mid-session, then continue the turn, and capture the exact outgoing request body to confirm it's empty/malformed JSON.permission_deniedtool result never produces a non-JSON/empty body on the following turn.Success criteria
permission_deniedon a compound Bash command no longer produces a400 invalid JSONerror on the following turn.