Image-only message sends empty text block with cache_control, 400s and kills conversation
Summary
The Claude Code desktop client sends an empty text content block (withcache_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-emptyAPI Error: 400 messages.112.content.1.text: cache_control cannot be set for empty text blocksAPI 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
- Start a remote-control daemon (
claude remote-control --name foo --permission-mode auto) and pair from the desktop client. - Attach an image to the prompt (paste/drag-drop).
- Send WITHOUT typing any text.
- 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 tocontent and marks it with cache_control: { type: "ephemeral" }. Both
properties independently violate the Messages API contract:
- A
textblock with empty string is invalid. cache_controlcannot 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)
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗