ThinkFacility

Error messages

messages: text content blocks must be non-empty

The message

messages: text content blocks must be non-empty
Anthropic API 1.8.0 read September 25, 2026Anthropic APIClaude400

What it means

Your request contains a text block whose text is an empty string, and the Claude API refuses the whole request. The word before the colon says where: messages or system.

What to do

Log the request body, find the {"type": "text", "text": ""}, and drop that block (or the whole empty turn) before sending. Retrying the same history fails the same way.

The Claude API returns this as HTTP 400 when something in your request is a text block with nothing in it. Here's the response body from a September 2026 bug report against an open-source legal chat app:

{"type":"error","error":{"type":"invalid_request_error","message":"messages: text content blocks must be non-empty"},"request_id":"req_..."}

The messages: prefix is where the empty block sits. The same check fires on the system prompt, and then the message starts system: instead. There's a sibling for text made only of spaces, system: text content blocks must contain non-whitespace text, which a LiteLLM report hit by sending a system message of three spaces.

Anthropic's error page files every malformed request under invalid_request_error and doesn't list this wording, so what follows comes from the reports. As of September 25, 2026 there are 283 GitHub issues quoting it.

Why the first message works and the second doesn't

This is the shape almost every report has. Turn one goes through, so the key and model are fine. Turn two fails, because now the app replays the history, and one stored turn has empty text.

Where does the empty turn come from? In the legal chat app, Claude's first reply used a tool step before answering. The app saved that turn with empty content, then rebuilt it next time with content ?? "", which makes an empty string instead of failing. In the Coddy agent, an assistant turn carried a thinking signature but no thinking text and no answer, and the serializer's fallback wrapped the empty content in a text block anyway.

Claude can also send back an empty answer on its own. Anthropic's Messages reference mentions "an empty string response from Claude" in passing (it's explaining that output_tokens is still above zero). If you store replies as they arrive and replay them, that's another way in.

When it says system:

An empty system block usually means the app always sends a system prompt, filled in or not. The VS Code report is a clean example: its Anthropic BYOK provider (bring your own key) started every system prompt as { type: 'text', text: '' } and sent it even when nothing was added. A one-line user message with no history failed with system: text content blocks must be non-empty. The reporter's proposed fix was to leave system out of the request when it's empty.

How to fix it

Log the outgoing JSON and search it for "text": "". Then fix the code that built it:

Retrying won't help. In anthropic-sdk-python 1.8.0 a 400 raises BadRequestError and isn't retried, and a chat with the bad turn saved in its history will keep failing until it's fixed or trimmed. If you only use someone else's app, a new chat gets its first message through (as it did in the legal chat app) while you report the bug.

Other lines the same feature prints

Match yours against these if the one at the top of the page is not quite it. They come from the same code and mean related things.

  • system: text content blocks must be non-empty
  • system: text content blocks must contain non-whitespace text
  • {"type":"error","error":{"type":"invalid_request_error","message":"messages: text content blocks must be non-empty"},"request_id":"req_..."}
  • ValidationException: messages: text content blocks must be non-empty.