Accumulated inline image base64 in session history causes 'Request too large (max 20MB)' — blocks all messages including /feedback

Status Closed — not planned
Maintainer reply None cached
Activity 16 comments · opened Apr 3, 2026 · closed Aug 2, 2026

Bug Description

Getting \Request too large (max 20MB). Double press esc to go back and try with a smaller file.\ error on text-only follow-up messages after prior inline screenshots have accumulated in the conversation history. The error also blocks submitting \/feedback\, making it difficult to report the issue when it occurs.

Suspected regression, reproduced on v2.1.91. The error was not observed between 2026-03-07 and 2026-04-03 across dozens of sessions on this machine. Historical search across all local Claude Code sessions shows only 3 affected sessions: one on 2026-03-07 and two on 2026-04-03. Note: absence from the changelog between v2.1.73–v2.1.91 does not prove no regression shipped — it only means none was documented.

Probable Root Cause (Session Forensics — Not Confirmed by Anthropic)

Inline image blocks (pasted/attached screenshots) are persisted as base64 in conversation history and re-sent with every subsequent API call. Once enough images accumulate, the serialized request exceeds the 20MB per-request cap — then every future message fails, even pure text ones with zero images.

Key forensic evidence (from independent Codex CLI audit of the affected session JSONL):

  • First \Request too large\ error occurred at JSONL line 356
  • First screenshot \Read\ call did not occur until JSONL line 390 — the \Read\ tool was NOT the initial trigger
  • At first failure: 14 inline image blocks with ~35.8M base64 characters already in history
  • Total session: 25 inline image blocks with ~55.2M base64 characters
  • Local image cache: 31 files totaling 52.6MB

Additional behavioral observations:

  • Even after \/rewind\, the base64 from previously-sent images persists in conversation state — text-only prompts still carry the accumulated image payload
  • Initially, providing file paths (which triggers the \Read\ tool) caused the error, while providing file URLs did not — but eventually even URLs stopped working
  • The error compounds: each \/rewind\ gives temporary relief but the underlying payload remains
  • The user was on a 1M-context model (Opus 4.6) at only 41% utilization (~409K tokens) — the 20MB wire-size cap is hit long before the semantic token limit

Prior Image-Related Fixes (Release Notes)

| Version | Release Date | Change |
|---------|-------------|--------|
| v1.0.28 | Pre-2026 | "Resizes images before upload to prevent API size limit errors" |
| v2.1.37 | Feb 7, 2026 | "Stripping images before sending to the compaction API" (#26188) |
| v2.1.43 | ~Feb 2026 | "Fixed image dimension limit errors to suggest /compact" |
| v2.1.71 | Mar 7, 2026 | "Fixed the Read tool putting oversized images into context when image processing failed" |
| v2.1.72 | Mar 10, 2026 | "Fixed oversized and truncated images from Bash data-URL output" |

The v2.1.71/v2.1.72 fixes addressed specific edge cases (Read tool failure path + Bash data-URL), but did not implement a general 20MB pre-flight payload size check or image pruning from accumulated conversation history.

Steps to Reproduce

  1. Start a Claude Code session (v2.1.91, Opus 4.6 1M context, Max subscription 20x)
  2. Paste or attach several screenshots/images during the conversation (inline, not necessarily via \Read\ tool)
  3. Continue working — the base64 of each image persists in conversation history
  4. After enough images accumulate (~14+ Retina screenshots = ~35MB base64), the serialized request exceeds 20MB
  5. Every subsequent message — including pure text with no images — fails with \Request too large (max 20MB)\
  6. \/feedback\ was not a reliable escape hatch during the failure state
  7. \/rewind\ gives temporary relief but the error recurs since image data remains in history
  8. Providing file paths (\Read\ tool) vs file URLs behave differently initially, but both eventually fail

Expected Behavior

  • Inline image data should be pruned, cached by reference, or excluded from re-serialization after initial processing
  • If re-sending is necessary, auto-compact should trigger before the 20MB cap
  • The error message should say "conversation payload too large" not "try with a smaller file"
  • \/feedback\ should always work regardless of conversation size
  • A 1M-context model should not hit a 20MB serialization wall at 41% token utilization

Session Evidence

| Date | Session | Role | Notes |
|------|---------|------|-------|
| 2026-03-07 | ec29e14c | Affected | First observed occurrence (14 error instances in JSONL) |
| 2026-03-08 to 2026-04-02 | (none) | — | ~4 weeks with no occurrences across many sessions |
| 2026-04-03 | 0d396357 | Primary affected session | 28 error instances, 14 inline images before first failure, 25 total |
| 2026-04-03 | 8a545e48 | Follow-up investigation | Session used to file this issue and research the bug (not independent repro) |

Environment

  • Claude Code: v2.1.91 (released Apr 2, 2026)
  • Subscription: Claude Max (20x)
  • Model: Opus 4.6 (1M context window)
  • macOS: Darwin 25.4.0
  • Context at failure: ~409,588 tokens (41% of 1M window)
  • Session: ~197 user turns, ~201 assistant messages

Related Issues (Same Root Cause)

  • #42256 — Read tool re-sends oversized images on EVERY subsequent message (OPEN)
  • #37418 — MCP screenshot makes session permanently unusable (OPEN)
  • #34751 — 99KB PNG triggers 20MB error; confirmed regression (OPEN)
  • #30542 — Best root-cause writeup; accumulated image data permanently kills conversations (CLOSED by stale bot, NOT fixed)
  • #38496 — Confirmed regression from v2.1.80 to v2.1.81 (CLOSED as duplicate)

Suggested Fixes

  1. Stop persisting base64 blobs in full — prune inline image data from conversation history after initial processing, or use a content reference/cache
  2. Add a pre-flight size check — before dispatching the API request, check serialized size and auto-compact or strip images if approaching 20MB
  3. Fix the error message — "conversation payload too large" not "try with a smaller file"
  4. Exempt \/feedback\ — truncate context before sending feedback so the reporting mechanism always works
  5. Show a warning at 80% of the cap — let users \/compact\ proactively before hitting the hard wall
  6. Differentiate file path (\Read\ tool) vs URL behavior — both should be handled consistently

View original on GitHub ↗

15 Comments

github-actions[bot] · 4 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/34751
  2. https://github.com/anthropics/claude-code/issues/42084
  3. https://github.com/anthropics/claude-code/issues/26019

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

nikkundra · 4 months ago

Update — Comprehensive Root Cause Analysis Added

This issue has been significantly updated since initial filing with forensic evidence from two independent sessions (Claude Code + Codex CLI audit):

Key findings:

  • The initial trigger is inline pasted/attached images accumulating as base64 in conversation history — NOT the Read tool (corrected from earlier version)
  • 14 inline image blocks (~35.8M base64 chars) were in history before the first failure
  • Even after /rewind, the base64 persists — text-only prompts still carry the full accumulated payload
  • File paths (Read tool) and file URLs behave differently initially, but both eventually fail
  • The error was absent for ~4 weeks (2026-03-08 to 2026-04-02), suggesting a regression in v2.1.91

This is NOT a duplicate of the issues flagged by the bot (#34751, #42084, #26019). While related, this issue provides:

  1. Forensic JSONL-level evidence pinpointing the exact failure mechanism
  2. Regression timeline with dates
  3. Proof that the Read tool is NOT the initial cause (correcting the narrative in #42256 and #30542)
  4. Evidence that /feedback itself is blocked by this error (UX loop)

The related issues were either closed by the stale bot without a fix, or lack this level of forensic detail.

cc @anthropics — requesting review of the updated root cause analysis and regression evidence above.

nikkundra · 4 months ago

Update — Issue Body Revised Based on Independent Forensic Review

The issue body has been significantly revised based on two independent code reviews by Codex CLI (GPT-5), which audited both the affected session JSONL and this follow-up session's work.

Changes made:

  1. Title updated — Now accurately reflects the root cause (accumulated inline image base64) rather than just one symptom (text-only messages)
  2. Root cause corrected — Earlier versions incorrectly blamed the Read tool. Forensic analysis proves the first Request too large error (JSONL line 356) occurred before the first Read tool call (line 390). Inline pasted/attached images are the initial trigger.
  3. Regression language softened — Changed from "confirmed regression" to "suspected regression, reproduced on v2.1.91" since we cannot prove a specific version introduced it
  4. Session 8a545e48 relabeled — Previously listed as independent repro; actually the follow-up investigation session (not a clean second reproduction)
  5. /feedback claim softened — Changed to "not a reliable escape hatch" rather than claiming it definitively fails with the same error
  6. Release notes analysis added — v2.1.71 (Mar 7) and v2.1.72 (Mar 10) fixed specific edge cases but did not implement general payload size checking or image pruning from history
  7. Additional observation — Even attaching one small image triggers the error once accumulated history is near the 20MB cap
  8. Environment details added — Max subscription (20x), ~197 turns, Opus 4.6 1M context

Methodology

The affected session JSONL was analyzed by an independent Codex CLI session which:

  • Counted exact inline image blocks and base64 character totals
  • Mapped the timeline of errors vs tool calls
  • Cross-referenced against the Claude Code changelog for prior fixes
  • Inspected the installed Claude Code binary for related strings
  • Conducted two separate review passes with corrections
nikkundra · 4 months ago

cc @anthropics — Title was updated from the original "Request too large (max 20MB) error on plain-text conversations with no images" to more accurately reflect the root cause identified through forensic JSONL analysis. The issue is not limited to text-only messages — it affects all messages once accumulated inline image base64 in session history exceeds the 20MB API request cap. The full issue body and prior comment document the forensic methodology and evidence.

nikkundra · 4 months ago

Release Notes Analysis

Prior image-related fixes in Claude Code:

| Version | Release Date | Change |
|---------|-------------|--------|
| v1.0.28 | Pre-2026 | "Resizes images before upload to prevent API size limit errors" |
| v2.1.37 | Feb 7, 2026 | "Stripping images before sending to the compaction API" (#26188) |
| v2.1.43 | ~Feb 2026 | "Fixed image dimension limit errors to suggest /compact" |
| v2.1.71 | Mar 7, 2026 | "Fixed the Read tool putting oversized images into context when image processing failed" |
| v2.1.72 | Mar 10, 2026 | "Fixed oversized and truncated images from Bash data-URL output" |

The v2.1.71/v2.1.72 fixes addressed specific edge cases (Read tool failure path + Bash data-URL output) but did not implement a general pre-flight payload size check or image pruning from accumulated conversation history.

This bug was reproduced on v2.1.91 (released Apr 2, 2026). The v2.1.91 changelog contains no image-related changes. We cannot determine from public changelogs alone whether a regression was introduced between v2.1.72 and v2.1.91, or whether the partial fixes simply never covered the accumulation scenario.

The per-image resize from v1.0.28 reduces individual image sizes, but the cumulative sum of 14+ resized Retina screenshots still exceeds 20MB when persisted in conversation history.

junaidtitan · 4 months ago

The image-strip strategy in Cozempic v1.6.11 directly addresses this — removes accumulated base64 image blocks, keeps only the most recent 20%. Prevents the "Request too large" error by keeping JSONL under the 20MB API limit.

pip install cozempic && cozempic init

nikkundra · 4 months ago
The image-strip strategy in Cozempic v1.6.11 directly addresses this — removes accumulated base64 image blocks, keeps only the most recent 20%. Prevents the "Request too large" error by keeping JSONL under the 20MB API limit. pip install cozempic && cozempic init

Unfortunately, I've had cozempic and was hoping this was going to solve this issue. It even might have helped for the period where I didn't seem to have this issue re-appear, but it's definitely back in full force... 😕

QuicksilverSlick · 4 months ago

💡 Session Recovery Workaround (No ffmpeg needed)

If your session is bricked by an oversized image, here's a clean recovery method that preserves your full context:

  1. Go to ~/.claude/projects/ (or C:\Users\<You>\.claude\projects\ on Windows)
  2. Find your project folder and locate the most recent .jsonl file (by modified date)
  3. Start a fresh session in your project directory
  4. Run /init to re-initialize project context
  5. Drag the .jsonl file into the chat and tell Claude: "Analyze this session log and get fully caught up on where we left off."

This works because the .jsonl files contain the complete conversation history. Feeding it into a fresh session gives you all the context without the corrupted state (the stuck oversized image causing the 400 error loop).

Full write-up with details: https://github.com/anthropics/claude-code/issues/13480#issuecomment-4237000378
zouchenzhen · 3 months ago

Adding one UX-specific angle from a Windows / Claude Code workflow.

The current issue already captures the root cause well: accumulated inline image/base64 history can make later text-only turns fail with Request too large, even when token context usage still looks safe.

The missing piece from a user perspective is that Claude Code exposes token context but not serialized request body size. For image-heavy UI/frontend workflows, those budgets diverge sharply.

Concrete UX requests:

  1. Show request-body byte usage alongside token usage, e.g. Request body: 24.5 MB / 32 MB.
  1. Preflight pasted/uploaded images before inserting them into conversation history:
  • original image size
  • estimated serialized/base64 contribution
  • warning if the image or accumulated request is near the limit
  1. If an image is too large or the session is near the limit, offer built-in actions:
  • downsample/compress image before insertion
  • run /compact
  • start a new session with a text summary
  1. After a 400/413 request-size failure, provide a recovery path:
  • remove the most recent image blocks from history
  • summarize or drop the most recent large tool result
  • run a targeted compact for image-heavy history

Longer context models do not solve this because the failure is serialized request-body bytes, not only token context. The UI currently makes this hard to predict because the visible context meter can look healthy while the request body is already near the hard limit.

My duplicate issue #56691 was auto-flagged against this issue, so I am adding the more specific UX requests here instead.

zouchenzhen · 3 months ago

Filed a related proposal at #56691 focused on the UX side: showing request body byte usage in real time and preflighting pasted/uploaded images before they hit the 32MB ceiling (complements the root-cause findings in this thread).

junaidtitan · 3 months ago

This is a painful one — accumulated base64 images silently bloating the request until everything breaks. I built Cozempic (https://github.com/Ruya-AI/cozempic) partly to address this. Its image-strip strategy removes inline base64 image blocks from session history, and the guard daemon can auto-prune before you hit the 20MB wall. pipx install cozempic && cozempic treat --rx standard on the affected session should clear the accumulated images. Would be curious if it helps your case.

junaidtitan · 3 months ago

Inline image base64 accumulating in session history is a known context killer — each screenshot stays in the JSONL forever and gets re-sent every turn. Cozempic has an image-strip strategy that specifically targets this: it removes base64 image data from older messages while preserving the text context around them. The guard daemon can do this automatically before you hit the 20MB wall. pip install cozempic && cozempic treat --rx standard to clean up an existing session, or cozempic guard to prevent accumulation. Would be interested to know if it resolves the blocking for you.

junaidtitan · 3 months ago

Been dealing with this exact problem — inline screenshots accumulate as base64 in the JSONL and eventually hit the 20MB wall. I built Cozempic which has an image-strip strategy that specifically targets base64 image blocks in session history, removing them before they snowball. The guard daemon can also auto-prune proactively so you never reach the limit. pip install cozempic && cozempic treat to clean an existing session, or cozempic guard for continuous monitoring. Would be curious if it helps with your workflow — happy to hear feedback.

jiseongnoh · 3 months ago

Cross-reference: this byte-payload-accumulation class also manifests in primarily-text sessions where tool output (long Bash stdout, repeated curl/API responses, persisted grep dumps) drives the payload past the 20-32MB ceiling — same wire-size-vs-token-count root cause class as the image accumulation here, just via a different content vector.

Recent data point on v2.x: hit payload est ~24 MB / 32 MB at only 26% token usage (257.9k/1M, Opus 4.7) with one small image paste total. Tool output accumulation dominated.

The v2.1.71/v2.1.72 fixes addressed image-specific paths. A general payload-size accounting layer (as proposed in #56691) would catch both classes — image accumulation and tool-output accumulation — with one mechanism. Bumping #56691 with similar framing.

Necmttn · 2 months ago

This class needs payload-byte accounting, not only token accounting.

Persist images as content refs with hash, byte size, MIME type, producer turn/tool id, and replay policy, then decide per request whether to inline, downsample, omit, or ask for confirmation. Preflight should include both current request bytes and projected next-turn replay bytes.

Regression: paste enough images to exceed the body budget later, send a text-only follow-up, and assert the client refs or prunes before the API rejects it.

---

_Generated with ax._

Showing cached comments. Read the full discussion on GitHub ↗