Image-only message sends empty text block with cache_control, 400s and kills conversation

Resolved 💬 3 comments Opened May 20, 2026 by drewmcelhany Closed Jun 18, 2026

Summary

The Claude Code desktop client sends an empty text content block (with
cache_control attached) when a user submits a message containing only
an image attachment and no typed text. The Messages API rejects with
400, and the conversation in the desktop app becomes unrecoverable.
Has occurred repeatedly in normal use (paste image, hit send before
typing).

Exact errors observed

  • API Error: 400 messages: text content blocks must be non-empty
  • API Error: 400 messages.112.content.1.text: cache_control cannot be set for empty text blocks
  • API Error: 400 messages.76.content.1.text: cache_control cannot be set for empty text blocks

The indices (112, 76) indicate this happens deep into long sessions —
making the lost context especially costly.

Repro

  1. Start a remote-control daemon (claude remote-control --name foo --permission-mode auto) and pair from the desktop client.
  2. Attach an image to the prompt (paste/drag-drop).
  3. Send WITHOUT typing any text.
  4. API returns 400; conversation becomes inert. Daemon (control + worker) stays alive; only the app-side thread is dead.

Root cause (apparent)

The serializer for outgoing messages appends an empty text block to
content and marks it with cache_control: { type: "ephemeral" }. Both
properties independently violate the Messages API contract:

  • A text block with empty string is invalid.
  • cache_control cannot be applied to an empty/whitespace text block.

Suggested fix

Before sending, strip any text blocks whose .text is empty/whitespace.
If a trailing cache breakpoint is desired, attach cache_control to the
last non-empty block (the image block, or the prior text block) instead
of synthesizing an empty one.

Workaround

Type any single character before sending. Reliable but easy to forget.

Impact

  • Loss of in-flight conversation context (JSONL backups exist but the

live session can't resume).

  • Daemon survives, so it's not a crash — purely a serialization bug at

the client/API boundary.

Environment

  • Claude Code CLI: 2.1.143
  • Node: v24.15.0
  • OS: Linux 6.17.0-29-generic (Ubuntu)
  • Mode: remote-control daemon (claude remote-control --name <X> --permission-mode auto)
  • Client: Claude desktop (Linux)

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗