Malformed image in Read tool poisons session — `400 Could not process image` loops indefinitely
Bug: malformed image in Read poisons session — API Error: 400 Could not process image loops forever
Repo: anthropics/claude-code
Severity: High — session becomes fully unrecoverable; user must abandon context.
Date hit: 2026-05-04
Model: Opus 4.7 (1M context). Also reproduced after /model swap — switching models did not clear the error.
Summary
When the Read tool ingests a PNG that the Anthropic API later refuses (400 invalid_request_error: "Could not process image"), the bad image stays in the conversation history. Every subsequent turn — including plain text replies, resume, and model switches via /model — re-sends that history, so every turn fails with the same 400. The session is bricked with no in-CLI recovery path.
Reproduction
- In a Playwright project, run a spec that produces a
trace.zipundertest-results/. - Extract the trace and ask Claude to
Readthe PNG screenshots insideresources/(these are often very small — the ones that triggered this were 5,840 B and 7,256 B). Some of these files appear to be malformed/empty thumbnails that the vision endpoint rejects. - The Read call returns:
````
API Error: 400 {"type":"error","error":{"type":"invalid_request_error","message":"Could not process image"},"request_id":"req_011CahbiTBcqL8xJyfbriq4F"}
- Every subsequent input fails identically:
resume→ 400 same error/modelswap to Opus 4.7 (1M) → succeeds, but nextresume→ 400 same error- Free-text message ("you cant process videos") → 400 same error
- Asking for a bug report ("create a bug report for claude code") → 400 same error
- Only escape: kill the session and start fresh.
Request IDs from the loop (for log correlation):
req_011CahbiTBcqL8xJyfbriq4Freq_011Cahbo9goFXVH1HVh9nFbcreq_011CahbpQ8V4qNUG8TASgdVAreq_011CahbuLDEWE71SN6sF2Gn8req_011CahbuyYYoZL7njU9ZBji5req_011CahbwMTSgtNh4FEdRBjgS
Expected behaviour
At least one of:
- Validate at the Read tool boundary. If the file is an image and the vision API would reject it (zero-byte, malformed, unsupported subtype, too small, etc.), surface a tool-level error instead of attaching the image content to the next request. The tool result can say "image could not be loaded" without poisoning the history.
- Recover from a poisoned turn. If a turn fails with
400 Could not process image, the harness should detect the image-related failure code and offer to drop the offending image attachment(s) from the transcript before retrying — similar to how compaction works. /modelandresumeshould at minimum let the user trim history. Right now both still re-submit the broken context.
Actual behaviour
- Bad image is silently retained.
- Every subsequent turn re-submits the bad image and fails with the same 400.
- No CLI affordance to inspect, edit, or strip the offending message.
/modelsucceeds (settings change, no model call) but does not clear the poison; the next inference call fails again.- Session is effectively dead; user loses all in-conversation state.
Impact
- Lost work: any uncommitted plan, todos, or partial reasoning in the session is unrecoverable.
- Trivially triggered: Playwright tracing produces these tiny PNGs by default, and any agent that follows traces to find evidence will hit this. Likely also reproducible with other malformed/edge-case images (HEIC, tiny GIFs, corrupt PNGs).
- Silent class of failure: nothing in the Read call indicates the image will be rejected by the next inference call — the failure surfaces one turn later.
Suggested fix priority
- Tool-level pre-validation on
Readfor image attachments (cheap, catches the common case). - Harness-level recovery when an inference call fails with an image-related 400 — strip the most recent image attachment(s) and retry, surfacing what happened to the user.
Environment
- Platform: darwin (macOS), Darwin 25.4.0
- Shell: zsh
- Model: Opus 4.7 (1M context) —
claude-opus-4-7[1m] - Project: Playwright E2E suite, traces from
test-results/nl-nl-checkout-*
This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗