Erros e códigos de estado
A chamada funciona no ambiente de desenvolvimento. Agora você está escrevendo a parte que vai rodar em produção – o bloco catch. Por si só, um erro HTTP de uma API de terceiros não esclarece muita coisa: um código de estado em vermelho e nenhuma resposta óbvia à única pergunta que importa às 3 da manhã – o problema está na minha requisição, na minha chave, no meu plano ou nos servidores deles? E quais desses erros pedem uma nova tentativa e quais devo mostrar ao usuário?
A Lingo.dev responde a isso com uma estrutura consistente. Todo erro dos endpoints destas páginas, síncronos ou assíncronos, retorna o mesmo objeto JSON, com um código de estado de uma tabela fixa. Já a API da plataforma em /v2 usa o formato padrão de detalhes de problemas; veja Erros da API da plataforma. O código de estado não é um rótulo; é uma instrução: ele indica se você deve corrigir a requisição, trocar a chave, adicionar créditos à conta, dar um tempo ou tentar novamente. Leia o código e saiba o próximo passo. Um único tratamento de erros, baseado no código de estado, cobre toda a API.
Nesta página
- Formato dos erros
- Códigos de estado
- Quais erros permitem novas tentativas
- 402 e 429: dois limites diferentes
- Onde ficam os erros de tarefas assíncronas
- Erros da API da plataforma
Formato dos erros#
Toda resposta fora da faixa 2xx tem o mesmo corpo: um objeto JSON com um único campo message que descreve o que deu errado.
{
"message": "Invalid API key"
}Esse é o contrato completo. Não há estrutura externa para descompactar nem formato de erro específico de cada endpoint para tratar à parte. Um 400 de /process/localize e um 404 de uma consulta de tarefa retornam o mesmo formato – só mudam o código de estado e o texto de message.
Baseie o tratamento no código de estado, não no texto da mensagem
O código de estado HTTP é o sinal estável – use-o para decidir como tratar cada erro. O texto de message foi escrito para quem está lendo um registro; trate-o como uma descrição, não como um código de erro legível por máquina, e não dependa de uma correspondência exata com esse texto.
Códigos de estado#
Sete códigos de estado cobrem todas as respostas. Aqui, eles estão agrupados por quem resolve o problema – porque esse agrupamento também define sua política de novas tentativas.
Você enviou algo que não pode ser atendido na requisição (corrija a requisição, não tente novamente às cegas):
| Estado | Significado |
|---|---|
400 Bad Request | A validação da requisição falhou – um campo ausente, um idioma inválido, um callbackUrl com HTTP (não HTTPS) ou um corpo de requisição malformado. |
401 Unauthorized | O cabeçalho X-API-Key está ausente ou é inválido. Veja Autenticação. |
403 Forbidden | A chave é válida, mas não tem acesso ao recurso solicitado. |
404 Not Found | O recurso – um engine, uma tarefa, um grupo de tarefas – não existe. |
Sua organização atingiu um limite da conta (resolva no faturamento):
| Estado | Significado |
|---|---|
402 Payment Required | A organização atingiu seu limite de crédito. |
429 Too Many Requests | A organização atingiu sua cota diária de tokens. Mude para um plano superior para aumentar o limite. |
Algo falhou do nosso lado (falha transitória – tente novamente):
| Estado | Significado |
|---|---|
500 Internal Server Error | Uma falha inesperada – um erro de banco de dados ou uma chamada de tradução que falhou em todos os modelos configurados no engine. |
Um 401 e um 403 parecem semelhantes, mas não representam o mesmo problema: 401 significa que não conseguimos identificar quem fez a chamada; 403 significa que identificamos a chave, mas ela não tem permissão de acesso. Para resolver um 401, é preciso agir sobre a própria chave (troque-a ou verifique-a); para resolver um 403, é preciso ajustar o acesso da chave.
Quais erros permitem novas tentativas#
A primeira pergunta de um integrador cético sobre qualquer tabela de erros costuma ser justamente a que fica sem resposta: em quais desses casos devo tentar novamente? O agrupamento acima responde a isso.
- 4xx – não tente novamente às cegas. Um
400,401,403ou404descreve uma condição na sua requisição. Repetir a mesma requisição gera o mesmo erro. Corrija os dados de entrada, a chave ou o ID do recurso e envie novamente. - 402 e 429 – dê um tempo e resolva o limite. Esses erros não são transitórios no nível da requisição; a próxima requisição esbarra no mesmo limite até que ele mude. Pare de repetir chamadas sem pausa, informe o limite e resolva a situação (adicione créditos ou mude para um plano superior).
- 500 – tente novamente com intervalos de espera. Essa é a única categoria realmente transitória. Um
500pode significar que todos os modelos configurados excederam o tempo limite naquela chamada; uma nova tentativa pode chegar a um modelo que esteja funcionando. Aumente os intervalos de espera exponencialmente e defina um número máximo de tentativas.
A API assíncrona informa os resultados de outra forma
Essa política de novas tentativas vale para chamadas síncronas que você faz diretamente. A API de localização assíncrona não fornece um código de estado para o resultado do trabalho: um POST retorna 202 assim que a requisição é aceita, e cada idioma de destino é processado como uma tarefa independente por meio de fluxos de trabalho persistentes em segundo plano. Você consulta periodicamente a tarefa ou recebe um webhook com o resultado, em vez de capturar um código de estado na chamada original. Veja onde ficam os erros de tarefas assíncronas.
402 e 429: dois limites diferentes#
Os dois códigos no nível da conta parecem dizer a mesma coisa – ambos soam como "você esgotou o limite" – e confundi-los leva o desenvolvedor à solução errada. São limites diferentes, com soluções diferentes:
402 Payment Required– a organização atingiu seu limite de crédito. Esse é um limite de faturamento. A próxima chamada continuará falhando até que a situação de faturamento da organização mude.429 Too Many Requests– a organização atingiu sua cota diária de tokens. Esse é um teto de consumo que se renova e pode ser aumentado com a mudança para um plano superior.
O motivo para separar esses casos no tratamento de erros: um 402 exige que uma pessoa tome uma providência no faturamento; um 429 indica uma cota que você pode esperar renovar ou aumentar mudando para um plano superior. Exibir uma mensagem genérica de "problema de pagamento" nos dois casos esconde qual ação o operador realmente precisa tomar.
O corpo de um 402 é igual ao de qualquer outro erro – é o código de estado que indica que se trata de um limite de crédito:
{
"message": "Organization has reached its credit limit"
}Onde ficam os erros de tarefas assíncronas#
Vale fazer uma distinção aqui, porque é nesse ponto que o tratamento por código de estado deixa de ser a ferramenta certa.
Os códigos de estado desta página são do nível de transporte: eles descrevem se a API aceitou e conseguiu atender à sua requisição HTTP. Um 202 da API assíncrona significa que sua requisição foi aceita – não que a tradução foi concluída com sucesso. Uma tarefa assíncrona pode ser aceita sem problemas e ainda assim falhar depois, quando um modelo excede o tempo limite durante a execução. Essa falha não aparece como um código de estado HTTP na chamada original; ela fica registrada na própria tarefa.
Assim, as falhas assíncronas aparecem em três lugares, nenhum deles nesta tabela:
- Estado de cada tarefa. Quando o processamento de um idioma falha, a tarefa apresenta
status: "failed"e umerrorMessage. Veja estados das tarefas. - Estado do grupo. Quando alguns idiomas são processados com sucesso e outros falham, o grupo informa
partial– as traduções dos idiomas concluídos com sucesso continuam sendo entregues. Veja como acompanhar um grupo de tarefas. - Entrega por webhook. Uma falha é entregue como um evento
translation.failedcom um campoerror. Veja entrega por webhook.
Há mais uma distinção que costuma causar confusão: a falha de uma etapa não crítica do fluxo de processamento não faz a tarefa falhar. A tarefa é concluída com completed_with_warnings e avisos por etapa, em vez de um erro. Isso é uma questão de observabilidade do fluxo de processamento, não de código de erro – veja como observar as execuções do fluxo de processamento.
Erros da API da plataforma#
A API da plataforma em https://api.lingo.dev/v2 responde aos erros de outra forma. Ela retorna detalhes de problemas conforme a RFC 9457, enviados como application/problem+json:
{
"type": "https://lingo.dev/docs/api/errors/glossary-in-use",
"status": 409,
"title": "Glossary in use",
"detail": "Glossary gls_1 cannot be deleted while 2 engines apply it. Detach it from those engines first.",
"id": "gls_1",
"engineCount": 2
}typeidentifica o problema. É um link para a página específica desse problema, que lista seus campos e os endpoints que o retornam. Usetypepara decidir como tratar o erro.statusrepete o código de estado HTTP.titleé um resumo curto, igual para todas as ocorrências de um mesmo tipo.detailinforma o que aconteceu desta vez e o que fazer em seguida. É escrito para uma pessoa, então exiba-o em vez de interpretá-lo por código.- Outros membros contêm os dados desta ocorrência, como
ideengineCountacima.detailé construído apenas a partir deles, então um cliente pode gerar seu próprio texto, no seu próprio idioma, com base emtypee nesses campos.
Uma requisição que falha na validação retorna 400 e lista cada valor inválido em errors, como pares { "path", "message" }. Todo endpoint também pode retornar service-unavailable (503), que permite novas tentativas com segurança usando intervalos de espera, e internal-server-error (500).
Cada código de estado segue uma regra:
| Estado | Significado |
|---|---|
401 | Quem fez a chamada não foi identificado. |
402 | Um limite do plano ou dos direitos de acesso, que pode ser ampliado mudando para um plano superior ou adicionando créditos. |
403 | Quem fez a chamada foi identificado, mas não pode realizar esta ação. |
404 | O recurso não existe ou quem fez a chamada não consegue vê-lo. |
409 | A requisição entra em conflito com o estado atual, por exemplo, um recurso que ainda está em uso. |
422 | A requisição está bem formada, mas uma regra a rejeita. |
429 | Um limite que se renova com o tempo. |
502 | Um provedor externo do qual o serviço depende falhou. |
503 | Uma falha temporária do nosso lado. Tente novamente com intervalos de espera. |
Próximos passos#
Um tratamento de erros bem estruturado começa pelos dois pontos que você encontrará primeiro durante a integração – a autenticação e os locais em que o processamento assíncrono informa seu próprio resultado.