Skip to content

API 400 on paste-image-without-text: empty text block persists in transcript, breaks all subsequent turns #50375

Description

@loungecrasher

Pasting image without accompanying text produces empty text block → API 400 on next turn

Summary

When the user pastes an image into Claude Code 2.1.x without typing any accompanying text, the resulting user message's content array contains an image block followed by an empty text block ({"type":"text","text":""}). The message sends successfully the first time, but every subsequent turn in that session re-sends the full transcript to the API, which rejects it with:

400: messages: text content blocks must be non-empty

(older variant on earlier paste-failures also produces: cache_control cannot be set for empty text blocks)

The session becomes unusable until the transcript JSONL file is manually repaired on disk.

Affected version

Claude Code 2.1.112 (current as of 2026-04-18). Likely all 2.1.x — bug observed since at least 2.1.90.

Reproduction

  1. Open any Claude Code session
  2. Paste an image (screenshot, copied file, etc.) into the prompt
  3. Hit enter WITHOUT typing any text
  4. (First turn may succeed)
  5. Send any further user message
  6. API rejects with 400 "text content blocks must be non-empty"

Evidence from our transcripts

After repairing two sessions, the corrupt blocks all matched this pattern:

{
  "role": "user",
  "content": [
    {"type": "image", "source": {...}},
    {"type": "image", "source": {...}},
    {"type": "text", "text": ""}    ← bug
  ]
}

Sometimes one image, sometimes 2+, always with a trailing empty text block.

Expected behavior

Either:

  • A: client strips the empty text block before adding to transcript (preferred)
  • B: client inserts a placeholder text block with minimal content (e.g., "(image attachment)")
  • C: API accepts empty text blocks on user messages when the array contains non-empty blocks

Impact / frequency

Single user, 10 agents on one host. Our most-paste-heavy agent hit this 8+ times in one day (running Sprint 14 review with screenshots). Each occurrence requires manual intervention on the JSONL file. We've built an auto-repair hook as a stopgap but the bug is in the client serialization, not the transcript.

Environment

  • macOS 15.x (Darwin 25.x)
  • Apple Silicon (M4)
  • Terminal.app and iTerm2 both affected
  • Codeman (web UI) sessions also affected

Workarounds currently in use

  1. Manual: always type at least one character alongside pasted images (easy to forget)
  2. Automated: UserPromptSubmit hook that scans the transcript for empty text blocks and strips them before each API call (working, but shouldn't be necessary)

Root-cause hypothesis

The paste handler likely always appends a trailing text block to the content array regardless of whether text was entered. If the text input is empty, the block is added with text: "" instead of being omitted.

Suggested fix

In the message serialization path, if the content array would end with an empty text block AND contains at least one non-text block before it, drop the empty text block before serialization.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:corearea:tuibugSomething isn't workingduplicateThis issue or pull request already existshas reproHas detailed reproduction stepsplatform:macosIssue specifically occurs on macOSstaleIssue is inactive

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions