Um 400 Bad Request é o servidor a recusar-se até a tentar. Olhou para o que chegou, decidiu que estava malformado o suficiente para não valer a pena continuar a analisar, e devolveu o único código que significa “isto não é um pedido que eu consiga ler”.

É um tipo de recusa diferente da maioria dos erros à sua volta. Um 404 significa que o servidor o entendeu perfeitamente e não tem nada nesse endereço. Um 403 significa que o entendeu e não o vai fazer. Um 400 significa que nunca chegou ao ponto de entender: a sintaxe estava errada, um cabeçalho estava malformado, o corpo não tinha a forma que o endpoint declarava. O pedido falhou antes de a pergunta sequer ser feita.

A palavra “cliente” está a trabalhar bastante aqui

Qualquer referência lhe dirá que um 4xx é um erro do cliente, e isso é tecnicamente verdade e na prática enganador. O cliente não é você. O cliente é o software que compôs o pedido, e num site moderno isso é quase sempre o próprio JavaScript da página.

Portanto um 400 num site que está a visitar normalmente significa que o frontend deles construiu um pedido que o backend deles não aceitava. O serializador de formulários de alguém enviou uma data no formato errado, uma chamada fetch enviou JSON sem dizer que era JSON, uma query string levava um carácter que ninguém codificou. O código de estado culpa o cliente, e o cliente é deles.

Isto importa porque inverte o conselho que acompanha a maioria dos erros. Com um 500 a culpa é obviamente do servidor e não há nada que possa fazer. Com um 400 a culpa soa a sua, o que manda as pessoas para vinte minutos a limpar caches e a reescrever URLs por causa de um bug que não poderiam ter provocado.

A família 4xx, que é confundida constantemente

400 Bad Request
O pedido estava malformado. O servidor não conseguiu analisá-lo bem o suficiente para agir sobre ele, por isso nada sobre quem você é ou o que pediu chegou a ser considerado
401 Unauthorized
O pedido estava bem. Não provou quem é, e o servidor quer credenciais
403 Forbidden
O pedido estava bem e ele sabe quem você é. Isto não lhe é permitido
404 Not Found
O pedido estava bem e não há nada nesse endereço

A linha que vale a pena reter é que só o 400 é sobre a forma do pedido. Os outros três descrevem todos um pedido bem formado a bater numa parede mais adiante, que é a razão pela qual o 401 e o 403 são trocados um pelo outro tantas vezes e nenhum dos dois é alguma vez confundido com um 400. Se está a receber um 400, pare de perguntar por permissões e comece a perguntar o que foi realmente enviado.

O único 400 que realmente pode corrigir do seu lado

Há uma excepção, e é comum o suficiente para valer a pena conhecê-la antes de dar o site como partido: um pedido cujos cabeçalhos são grandes demais.

Os cookies são cabeçalhos. Um site que acumulou alguns anos deles, ou um fluxo de autenticação repetido vezes suficientes para empilhar estado de sessão, pode empurrar o bloco de cabeçalhos para além do limite que o servidor está disposto a ler. A maioria dos servidores responde a isso com um 400, às vezes com uma página que diz “Request Header Or Cookie Too Large” e muitas vezes com nada.

O sinal é que o segue num site e em mais nenhum, sobrevive a um recarregamento e desaparece de imediato numa janela privada. Se isso descreve o que está a ver, apagar os cookies desse site resolve, e é o único 400 em que os habituais remédios caseiros são a resposta a sério. Se uma janela privada mostrar o mesmo 400, não é isto, e nenhuma quantidade de limpeza lhe vai tocar.

Se o site é seu

A resposta que o utilizador recebeu está quase vazia por desenho, por isso a causa está no que foi enviado e não no que voltou. Um punhado de coisas explica a maioria deles.

Um corpo malformado ou mal escrito. Um POST a levar JSON que não analisa, ou que analisa e não corresponde ao esquema contra o qual o endpoint valida. Muitas vezes um campo que é null onde a API declarava uma string, ou um número que chega como "12" porque um serializador de formulários transforma tudo em strings.

Um Content-Type em falta ou errado. Um corpo que o servidor aceitaria de bom grado, enviado sem dizer o que é, ou etiquetado como text/plain quando o analisador quer application/json. O pedido é bem formado à vista e ilegível para aquilo que tem de o ler.

Alguma coisa no URL que nunca foi codificada. Um espaço em bruto, um % perdido que não é o início de uma sequência de escape, um parâmetro de query a levar um URL próprio com o seu próprio &. Alguns destes são rejeitados pelo servidor web antes de a sua aplicação sequer os ver, que é a razão pela qual não deixam rasto no log da aplicação.

Cabeçalhos que o proxy não aceita. O caso dos cookies acima, mas também um cabeçalho Authorization demasiado grande ou um cabeçalho a levar uma mudança de linha. Estes são normalmente recusados na borda, pelo nginx ou por uma CDN, e o 400 que volta é desse proxy, não seu.

Esse último grupo é a razão pela qual um 400 pode ser genuinamente invisível por dentro. Se a recusa aconteceu antes de o pedido chegar ao seu código, não há nenhuma linha no log da aplicação para encontrar, e pode passar uma tarde à procura de um bug num sítio onde nunca lhe foi permitido chegar.

Porque é que um 400 é difícil de perseguir depois do facto

Um 400 é inteiramente uma afirmação sobre um pedido que já não existe. Quando alguém lhe fala dele, a coisa malformada já desapareceu: tem um código de estado, uma hora aproximada e um URL que provavelmente funciona bem quando é você a escrevê-lo, porque aquilo que partiu estava num cabeçalho ou num corpo que não consegue ver a partir da barra de endereço.

Reproduzi-lo significa reconstruir o pedido exacto, o que significa saber o que a página enviou, e essa é justamente a única coisa que uma captura de ecrã de uma página de erro não lhe consegue dizer.

Session Replay

Extensão gratuita do Chrome. Um clique na página que se está a portar mal captura a captura de ecrã, a consola e o registo de rede, e dá-lhe um link para colar no ticket.

Obter a extensão

O registo de rede é o ponto todo aqui. Contém o pedido que recebeu o 400 com o seu método, os seus cabeçalhos e o seu corpo, que é exactamente o material de que um 400 se queixa. Quem pegar no relatório consegue ler o que foi enviado em vez de o adivinhar, e isso é normalmente a investigação inteira.

Num parágrafo

Um 400 Bad Request significa que o servidor não conseguiu analisar o que chegou e desistiu antes de o considerar, o que faz dele o único 4xx que é sobre a forma do pedido em vez de ser sobre permissão ou existência. Chama-se erro do cliente, mas o cliente é normalmente o próprio JavaScript do site, por isso como visitante em geral não há nada a corrigir, com uma excepção a sério: um bloco de cookies ou de cabeçalhos que cresceu demais, coisa que uma janela privada confirma em segundos. Se o site é seu, olhe para o que foi enviado: um corpo que não se analisa, um content type em falta, um URL não codificado, ou um cabeçalho que o seu proxy recusou antes de o seu código sequer correr.