claude-code - 💡(How to fix) Fix Malformed image (bad PNG bytes / paste / 404'd URL) permanently bricks the session — `API Error: 400 Could not process image` on every turn [2 comments, 2 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#53228Fetched 2026-04-26 05:21:05
View on GitHub
Comments
2
Participants
2
Timeline
8
Reactions
0
Timeline (top)
labeled ×4commented ×2closed ×1cross-referenced ×1

When Claude Code attaches an image whose bytes the API cannot decode (corrupted PNG, file with .png extension that's actually HTML, base64 paste with a bad header, etc.), the API responds with HTTP 400 Could not process image. Claude Code does not remove the offending content from the conversation, so every subsequent prompt — including a /exit followed by --resume — re-sends the same poisoned context and fails the same way. The session becomes permanently unusable.

Error Message

⎿ API Error: 400 {"type":"error","error":{"type":"invalid_request_error","message":"Could not process image"}}

Root Cause

Root cause (two compounding issues)

Fix Action

Fix / Workaround

  • Validate magic bytes before constructing an image content block. Reject (or downgrade to a text attachment that says "couldn't read as image, here's a hex preview") when the header doesn't match the declared media type. Same check for prompt paste of a base64 string.
  • On 400 Could not process image, surface a clear error to the user and offer to drop the most recently added image content block(s) from the context, then retry. Currently the user has zero recourse from the TUI.

Code Example

echo '<!DOCTYPE html><html>oops</html>' > /tmp/fake.png

---

API Error: 400 {"type":"error","error":{"type":"invalid_request_error","message":"Could not process image"}}
RAW_BUFFERClick to expand / collapse

Pasting / reading a malformed PNG bricks the session permanently with API Error: 400 Could not process image

Summary

When Claude Code attaches an image whose bytes the API cannot decode (corrupted PNG, file with .png extension that's actually HTML, base64 paste with a bad header, etc.), the API responds with HTTP 400 Could not process image. Claude Code does not remove the offending content from the conversation, so every subsequent prompt — including a /exit followed by --resume — re-sends the same poisoned context and fails the same way. The session becomes permanently unusable.

Repro

  1. Save a non-image file with a .png extension (e.g. an HTML error page, or some random base64 the user pastes from a webpage):
    echo '<!DOCTYPE html><html>oops</html>' > /tmp/fake.png
  2. In Claude Code, ask the model to look at /tmp/fake.png. The model uses Read, which auto-attaches the file as an image content block based on extension.
  3. Next API call fails immediately:
    ⎿ API Error: 400 {"type":"error","error":{"type":"invalid_request_error","message":"Could not process image"}}
  4. Type any message. Same 400.
  5. /exit, then claude --resume <that session>. Same 400 — context still contains the bad image.
  6. Session is bricked. The only escape is to manually edit the JSONL on disk and replace the bad image block.

Same outcome if the user pastes a base64 PNG into the prompt where the base64 is truncated, has a non-PNG header, or is otherwise malformed.

Root cause (two compounding issues)

  1. No validation before sending. The Read tool (and prompt paste) accepts content with image/png media type without checking the magic bytes. A 2860-byte file starting with <!DOCTYP is happily encoded and shipped as image/png.
  2. No recovery from a 400. When the API returns invalid_request_error: Could not process image, Claude Code keeps the content block in conversation state and resends it on every subsequent turn. There is no "this image is poison, drop it" path.

Either fix alone would prevent permanent bricking. Both should be fixed.

Suggested fixes

  • Validate magic bytes before constructing an image content block. Reject (or downgrade to a text attachment that says "couldn't read as image, here's a hex preview") when the header doesn't match the declared media type. Same check for prompt paste of a base64 string.
  • On 400 Could not process image, surface a clear error to the user and offer to drop the most recently added image content block(s) from the context, then retry. Currently the user has zero recourse from the TUI.

Real-world example

Today I asked Claude Code to curl a few logo URLs and check them. One returned an HTML error page that got saved as g-test.png. The model's next Read of that path put the HTML bytes into an image/png content block. The session bricked. After /exit and --resume, the API kept failing on the same image. I had to:

  1. Locate the session file at ~/.claude/projects/<slug>/<uuid>.jsonl
  2. Parse it, find the one bad tool_resultimage/png block whose base64 decoded to <!DOCTYPE html>
  3. Replace it with a text placeholder
  4. Resume

That's a lot of manual recovery for a "the model fetched a URL that 404'd" scenario.

Environment

  • Claude Code 2.1.119 / 2.1.120 (also reproducible on prior versions, this is not a regression)
  • Linux, Bun-bundled native binary
  • API endpoint: production Anthropic API

Impact

  • Sessions with hours of context can be killed by a single corrupted image (URL 404 returning HTML, partial paste, broken file).
  • --resume doesn't help — the poison is in the persisted JSONL.
  • The error message is a generic 400; nothing in the TUI tells the user which image is bad or how to remove it. Users with no JSONL spelunking skills lose the entire session.

extent analysis

TL;DR

Validate image magic bytes before sending and implement error handling to drop poisoned image content blocks on API errors.

Guidance

  • Validate magic bytes for image/png media type before constructing an image content block to prevent sending malformed images.
  • Implement error handling for 400 Could not process image errors to surface a clear error to the user and offer to drop the most recently added image content block(s) from the context.
  • Consider adding a "this image is poison, drop it" path to prevent permanent session bricking.
  • Review the Read tool and prompt paste functionality to ensure they handle image validation and error handling correctly.

Example

No code snippet is provided as the issue does not imply a specific code change, but rather a design and implementation change to handle image validation and error handling.

Notes

The issue highlights two compounding problems: lack of validation before sending and no recovery from API errors. Fixing either issue would prevent permanent bricking, but addressing both is recommended for a more robust solution.

Recommendation

Apply a workaround to validate image magic bytes and implement error handling for 400 Could not process image errors, as upgrading to a fixed version is not implied in the issue. This will help prevent session bricking and provide a better user experience.

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 Malformed image (bad PNG bytes / paste / 404'd URL) permanently bricks the session — `API Error: 400 Could not process image` on every turn [2 comments, 2 participants]