Erro de API 400 "Text Content Blocks Must Be Non-Empty": Causas e 5 Correções significa que uma solicitação da Anthropic Messages API contém pelo menos um bloco de texto cujo valor text está vazio. A solicitação pode parecer válida no nível da mensagem, mas o provedor a rejeita antes da geração porque um bloco de conteúdo de texto deve conter pelo menos um caractere.
A correção rápida é simples: remova blocos de texto vazios, elimine a entrada do usuário composta apenas por espaços em branco antes de construir a solicitação e nunca envie blocos de placeholder como {"type":"text","text":""}. A parte mais difícil é descobrir onde esses blocos são introduzidos. Em apps de produção, eles geralmente vêm de rascunhos da interface de chat, trechos de recuperação vazios, limpadores de markdown, variáveis de template, buffers de transcrição em streaming ou adaptadores multimodais que constroem um array de conteúdo antes de saber se há texto presente.
Use este guia para depurar o erro, ajustar o construtor da solicitação e adicionar uma proteção de pré-validação para que o mesmo 400 não volte a ocorrer.
Resposta Rápida: Erro de API 400 "Text Content Blocks Must Be Non-Empty"
A Anthropic aceita o content da mensagem como uma string simples ou como um array de blocos de conteúdo tipados. No formato de array, um bloco de texto se parece com isto:
{
"type": "text",
"text": "Resuma este ticket de suporte."
}
Isso falha porque o campo text está vazio:
{
"type": "text",
"text": ""
}
Isso também pode falhar na prática se seu app normaliza um valor composto apenas por espaços em branco para uma string vazia:
{
"type": "text",
"text": " "
}
A regra mais segura é:
- Remova espaços dos valores de texto antes de construir a solicitação da Anthropic.
- Descarte blocos de texto cujo texto, após remoção dos espaços, esteja vazio.
- Se uma mensagem não tiver mais blocos de conteúdo, não envie essa mensagem.
- Registre a forma do payload sanitizado sem registrar o texto privado do prompt.
- Adicione um teste unitário para strings vazias, espaços em branco, nulos e resultados de recuperação vazios.
Essa é a correção prática para Erro de API 400 "Text Content Blocks Must Be Non-Empty": Causas e 5 Correções.
Por que Este Erro Acontece
A Messages API da Anthropic usa turnos de conversa estruturados. Cada mensagem de entrada tem um role e um content. O valor content pode ser uma única string ou pode ser um array de blocos, como blocos de texto e imagem. A documentação oficial de referência da Messages API descreve o conteúdo em string como um atalho para um bloco de texto e lista text em um bloco de texto com minLength: 1.
A referência de erros da Anthropic classifica HTTP 400 como invalid_request_error: um problema com o formato ou o conteúdo da solicitação. Portanto, isso não é limite de taxa, falha de autenticação, indisponibilidade do provedor nem um problema de qualidade do modelo. É um problema de validação da solicitação.
Para equipes de produto de IA, a lição operacional é importante: repetir a mesma solicitação não vai ajudar. Você precisa corrigir o payload antes de tentar novamente.
Cinco Causas Comuns
1. Entrada de Chat Vazia Chega à API
O caminho mais comum é um compositor de chat que permite que o usuário envie um rascunho vazio ou um rascunho que se torna vazio após o tratamento de espaços em branco.
Solicitação inválida:
{
"model": "claude-sonnet-5",
"max_tokens": 512,
"messages": [
{
"role": "user",
"content": [
{ "type": "text", "text": "" }
]
}
]
}
Corrija isso antes da chamada da API:
const input = userInput.trim();
if (!input) {
throw new Error("O texto da mensagem é obrigatório antes de chamar a Anthropic.");
}
const messages = [
{
role: "user",
content: input
}
];
Use uma mensagem de validação em nível de produto na interface. Não deixe o backend descobrir um prompt vazio por meio de um 400 do provedor.
2. A Recuperação Adiciona Trechos Vazios
Pipelines de RAG часто mapeiam documentos recuperados em seções do prompt. Se um resultado de recuperação tiver um trecho vazio, um corpo HTML removido ou um campo de OCR com falha, o adaptador pode criar um bloco de texto vazio.
Adaptador ruim:
const content = retrievedDocs.map((doc) => ({
type: "text",
text: doc.cleanedText
}));
Adaptador mais seguro:
const content = retrievedDocs
.map((doc) => (doc.cleanedText ?? "").trim())
.filter(Boolean)
.map((text) => ({ type: "text", text }));
Se o modelo precisar de contexto de origem, mantenha também uma contagem dos trechos descartados. Se todos os trechos recuperados estiverem vazios, pare e retorne um erro de recuperação em vez de enviar um prompt vazio.
3. Variáveis Do Template Renderizam Nada
Templates de prompt são outra causa frequente de Erro de API 400 "Text Content Blocks Must Be Non-Empty": Causas e 5 Correções. Um template pode parecer preenchido no código, mas renderizar uma seção vazia em tempo de execução:
const prompt = `
Mensagem do cliente:
${customerMessage}
`;
Se customerMessage for undefined, null ou estiver em branco após a limpeza, o prompt final pode ficar inútil ou vazio.
Use campos obrigatórios explícitos:
function requiredText(name: string, value: unknown): string {
const text = String(value ?? "").trim();
if (!text) {
throw new Error(`Campo obrigatório do prompt ausente: ${name}`);
}
return text;
}
const prompt = `Mensagem do cliente:\n${requiredText("customerMessage", customerMessage)}`;
Isso transforma um erro genérico do provedor em um erro local da aplicação com o nome do campo ausente.
4. Builders Multimodais Adicionam Um Bloco De Texto Placeholder
Equipes que constroem fluxos de imagem + texto às vezes inicializam arrays de conteúdo com um bloco de texto placeholder e o preenchem depois. Se o texto for opcional e nenhum texto chegar, o placeholder permanece vazio.
Padrão ruim:
[
{ "type": "text", "text": "" },
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/png",
"data": "..."
}
}
]
Padrão mais seguro:
const content: Array<Record<string, unknown>> = [];
const instruction = optionalInstruction.trim();
if (instruction) {
content.push({ type: "text", text: instruction });
}
content.push({
type: "image",
source: imageSource
});
Construa blocos apenas quando o conteúdo correspondente existir. Não use blocos de texto vazios como separadores.
5. A Compactação do Histórico de Mensagens Deixa Turnos em Branco
Assistentes de longa execução frequentemente compactam ou resumem turnos anteriores. Se a etapa de compactação remover o corpo de uma mensagem, mas mantiver o turno no histórico, sua solicitação pode conter uma mensagem vazia do assistente ou do usuário.
Exemplo de falha:
{
"role": "assistant",
"content": [
{ "type": "text", "text": "" }
]
}
Use um saneador de histórico antes de cada chamada:
type TextBlock = { type: "text"; text: string };
type Message = { role: "user" | "assistant"; content: string | TextBlock[] };
function sanitizeMessages(messages: Message[]): Message[] {
return messages.flatMap((message) => {
if (typeof message.content === "string") {
const text = message.content.trim();
return text ? [{ ...message, content: text }] : [];
}
const content = message.content
.map((block) => ({ ...block, text: block.text.trim() }))
.filter((block) => block.type !== "text" || block.text.length > 0);
return content.length ? [{ ...message, content }] : [];
});
}
Depois, verifique se pelo menos uma mensagem permanece antes de chamar a API.
Um Validador de Pré-verificação Copiável
Use um validador de pré-verificação da solicitação perto da fronteira final da rede. Isso detecta blocos vazios mesmo que uma UI, template, RAG ou módulo de memória a montante os ignore.
type ContentBlock =
| { type: "text"; text?: unknown }
| { type: string; [key: string]: unknown };
type AnthropicMessage = {
role: "user" | "assistant";
content: string | ContentBlock[];
};
export function validateAnthropicMessages(messages: AnthropicMessage[]) {
const cleaned = messages.flatMap((message, messageIndex) => {
if (typeof message.content === "string") {
const text = message.content.trim();
return text ? [{ ...message, content: text }] : [];
}
const content = message.content.flatMap((block, blockIndex) => {
if (block.type !== "text") return [block];
const text = String(block.text ?? "").trim();
if (!text) {
console.warn("Dropped empty Anthropic text block", {
messageIndex,
blockIndex
});
return [];
}
return [{ ...block, text }];
});
return content.length ? [{ ...message, content }] : [];
});
if (!cleaned.length) {
throw new Error("Anthropic request has no non-empty message content.");
}
return cleaned;
}
Isso é intencionalmente conservador. Ele remove blocos de texto vazios, preserva blocos que não são de texto, remove mensagens vazias e se recusa a chamar o modelo se não restar conteúdo de mensagem utilizável.
Versão em Python
Se o seu backend for Python, use a mesma verificação de fronteira:
def sanitize_anthropic_messages(messages):
cleaned_messages = []
for message_index, message in enumerate(messages):
content = message.get("content")
if isinstance(content, str):
text = content.strip()
if text:
cleaned_messages.append({**message, "content": text})
continue
if isinstance(content, list):
cleaned_blocks = []
for block_index, block in enumerate(content):
if block.get("type") != "text":
cleaned_blocks.append(block)
continue
text = str(block.get("text") or "").strip()
if text:
cleaned_blocks.append({**block, "text": text})
else:
print(
"Bloco de texto Anthropic vazio descartado",
{"message_index": message_index, "block_index": block_index},
)
if cleaned_blocks:
cleaned_messages.append({**message, "content": cleaned_blocks})
if not cleaned_messages:
raise ValueError("A solicitação Anthropic não tem conteúdo de mensagem não vazio.")
return cleaned_messages
Mantenha a estrutura dos metadados do log. Não registre prompts brutos de usuários, documentos de clientes ou texto privado de recuperação, a menos que sua política de privacidade e fluxo de trabalho de depuração permitam isso explicitamente.
Lista de Verificação de Depuração
Quando Erro de API 400 "Text Content Blocks Must Be Non-Empty": Causas e 5 Correções aparece em produção, depure nesta ordem:
| Verificação | O que inspecionar | Correção |
|---|---|---|
| Entrada da UI | Rascunho do usuário vazio ou contendo apenas espaços em branco | Bloqueie o envio até que exista texto sem espaços após o trim |
| Modelo de prompt | Variável obrigatória renderizada como vazia | Valide os campos obrigatórios pelo nome |
| Chunks de RAG | cleanedText vazio, resultado de OCR ou corpo markdown |
Filtre os chunks e falhe se todo o contexto estiver vazio |
| Solicitação multimodal | Bloco de texto de preenchimento antes de um bloco de imagem/arquivo | Envie blocos de texto somente quando houver texto |
| Compactação do histórico | Turnos vazios do usuário ou do assistente após a sumarização | Sanitize a lista final de mensagens |
| Fronteira de rede | O payload final ainda contém text: "" |
Adicione um validador de preflight e testes unitários |
O payload final de rede é a fonte da verdade. Se seus logs não mostrarem nenhum bloco de texto vazio, confirme que o SDK não está convertendo null, undefined ou um array vazio em um bloco de texto durante a serialização.
Testes Unitários a Adicionar
No mínimo, adicione testes para estes casos:
const cases = [
{ name: "string vazia simples", content: "" },
{ name: "string de espaços em branco simples", content: " " },
{ name: "bloco de texto vazio", content: [{ type: "text", text: "" }] },
{ name: "campo de texto ausente", content: [{ type: "text" }] },
{ name: "campo de texto nulo", content: [{ type: "text", text: null }] },
{ name: "bloco de texto válido", content: [{ type: "text", text: "Hello" }] }
];
O comportamento esperado deve ser explícito:
- Mensagens vazias somente de texto são removidas ou rejeitadas localmente.
- Texto válido é mantido com espaços em branco iniciais e finais removidos.
- Blocos de conteúdo que não são texto são preservados.
- Uma solicitação sem conteúdo utilizável gera erro antes de chamar a Anthropic.
- O erro lançado identifica a fronteira da sua aplicação, não apenas a resposta do provedor.
Onde a Flatkey Se Encaixa
Se sua equipe roteia o tráfego do Claude por meio da Flatkey, mantenha a mesma disciplina de payload da Anthropic. O guia do SDK da Anthropic da Flatkey mostra base_url="https://router.flatkey.ai" para o caminho do SDK da Anthropic, enquanto a API compatível com OpenAI usa https://router.flatkey.ai/v1 para solicitações no estilo chat-completions. Use a rota que corresponda ao seu cliente e ao formato do endpoint.
Para este erro, a Flatkey é mais útil como a camada operacional em torno da correção:
- Mantenha um único lugar para verificar se a solicitação chegou ao gateway.
- Compare o status da solicitação e as evidências de uso após uma nova tentativa bem-sucedida.
- Mantenha um pequeno teste de fumaça separado do prompt completo do usuário.
- Evite misturar solicitações no formato Anthropic e solicitações compatíveis com OpenAI no mesmo adaptador.
Se você estiver escolhendo uma rota para uma carga de trabalho do Claude, leia Proxy de API do Claude vs Roteador Multimodelo. Se você estiver padronizando como os engenheiros fazem sua primeira chamada segura, mantenha o guia rápido da API da Flatkey por perto. Para verificações de produção mais amplas, combine isso com métricas de API de roteamento de IA e o guia do catálogo de modelos de IA.
O Que Não Fazer
Não resolva Erro de API 400 "Text Content Blocks Must Be Non-Empty": Causas e 5 Correções com novas tentativas cegas. O provedor está dizendo que a solicitação está malformada.
Evite estes padrões antiéticos:
| Padrão antiético | Por que falha |
|---|---|
| Repetir o mesmo payload | Um erro de validação determinístico continuará falhando |
Substituir texto vazio por "." |
Isso oculta a perda de dados na origem e pode alterar o comportamento do modelo |
| Enviar turnos vazios do assistente | Isso polui o histórico e pode quebrar a continuação da resposta |
| Registrar prompts completos para depuração | Isso pode expor dados de clientes ou segredos |
| Corrigir apenas a interface | Trabalhos de backend, RAG, webhooks e loops de agentes ainda podem criar blocos vazios |
A correção duradoura é validar o conteúdo tanto na fronteira do produtor quanto na fronteira final da API.
FAQ
Isso é uma interrupção da Anthropic?
Não. Um erro 400 invalid_request_error para blocos de texto vazios é um problema de validação da requisição. Verifique o payload que sua aplicação envia.
Posso enviar uma string simples em vez de um array de blocos de texto?
Sim. A Messages API da Anthropic permite que o content da mensagem seja uma string, e a documentação descreve isso como um atalho para um único bloco de texto. Use uma string quando você só precisar de texto simples. Use um array quando precisar de vários blocos ou de entrada multimodal.
Devo considerar espaço em branco como não vazio?
Trate texto composto apenas por espaço em branco como vazio no seu próprio validador. Mesmo que um provedor o aceitasse, isso não é conteúdo útil para prompt e geralmente indica um bug de interface, template ou recuperação.
Mensagens só com imagem podem funcionar?
Uma requisição multimodal não precisa de um placeholder de texto vazio. Se você incluir um bloco de imagem, crie o bloco de imagem diretamente e adicione um bloco de texto somente quando tiver texto de instrução real.
O que devo registrar nos logs?
Registre a contagem de mensagens, os tipos de bloco de conteúdo, os índices dos blocos, o modelo, o endpoint, a rota, o código de status e o ID da requisição, se उपलब्धível. Evite registrar o texto completo do prompt, a menos que as políticas de privacidade da sua equipe permitam.
Referências Oficiais
- Referência da Messages API da Anthropic: https://platform.claude.com/docs/en/api/messages
- Referência de erros da API da Anthropic: https://platform.claude.com/docs/en/api/errors
- Guia da Messages API da Anthropic: https://platform.claude.com/docs/en/build-with-claude/working-with-messages
- Guia do SDK Anthropic da Flatkey: https://docs.flatkey.ai/guides/anthropic-sdk.md
- Visão geral da API da Flatkey: https://docs.flatkey.ai/api-reference/overview.md



