Processamento de erros e códigos de estado
1) Por que normalizar erros
Um único contrato de erros acelera a depuração dos clientes, reduz as retraias falsas e torna o RCA reproduível. Bom sistema:- previsivelmente codifica o tipo de problema,
- dá ao cliente dicas válidas (o que fazer a seguir),
- protege contra a fuga de peças internas,
- compatível com retraias e idimpotência.
2) Princípios de design
1. Um padrão de erro para todos os serviços (REST/GraphQL/gRPC/webhooks).
2. Semântica clara de retrações, que códigos retrabalhar, quais não.
3. Fail-closed em operações write: melhor 4xx/5xx do que não-conservação silenciosa.
4. Sem vazamentos: não revelar SQL, pilhas, configs, ID interna.
5. Traçado: devolva sempre 'trace _ id '/' correlation _ id'.
6. A localização de mensagens é opcional, mas os códigos e 'reason' permanecem estáveis.
3) Formato unificado (Problem Details/JSON)
Formato básico recomendado (compatível com RFC 7807):json
{
"type": "https://errors.example.com/auth/invalid-token",
"title": "Invalid access token",
"status": 401,
"code": "AUTH_INVALID_TOKEN",
"detail": "Token expired or signature invalid.",
"instance": "/api/v1/payments/12345",
"trace_id": "01HX3...ABC",
"hint": "Obtain a new token via OAuth2 refresh.",
"meta": {
"scope": "payments:write",
"policy": "deny-by-default"
}
}
Explicações:
- 'tipo' é um URL estável de classe de erro.
- 'código' é um código de domínio de máquina curta (estável entre os lançamentos).
- 'hint' - o que fazer ao cliente (repetição, atualizar o token, alterar as opções).
- 'metá' - peças seguras (sem segredos e PII).
4) Mapa de códigos de estado (conjunto mínimo)
Autenticação/Autorização
400 Bad Request - validação estrutural/esquema.
401 Unauthorized - não/nevalideno token. Adicione 'WWW-Autenticate'.
403 Forbidden - autenticado, mas nenhum direito/política foi negado.
404 Not Found - disfarce a existência do recurso quando não tiver permissões.
409 Conflict - conflito de versões/estados (optimistic lock, idempotidade).
451 Unavailable For Legal Reasons - unidade de conformidade/jurisdição.
Limites e proteção
408 Request Timeout - o cliente envia o corpo lentamente demais.
409/425 Too Early - proibição de repetição precoce em 0-PTT/TLS 1. 3.
429 Too Many Requests - com 'Retry-After' e política de limite.
499 Cliente Closed Request - (no perímetro/NGINX) o cliente rompeu a conexão.
Dados e Regras de Negócios
422 Unprocessable Conteúdo - a validação de negócios foi feita, mas o significado não é correto.
423 Locked - recurso bloqueado (KYC review, AML freeze).
409 Conflict - duplo envio, corrida, limite de estado (por exemplo, «já em processamento»).
410 Gone - endpoint/recurso removido (deprekate concluído).
Servidores
500 Internal Server Erro - erro desconhecido; Não revelar detalhes.
502 Bad Gateway - Dependência devolveu erro/proxy.
503 Service Unavailable - degradação/trabalho programado; adicionar 'Retry-After'.
504 Gateway Timeout - timeout das dependências.
5) Semântica de retraias e idempotação
Não é possível retrair: 400/ 401/403/404/422 (se o cliente não alterar a solicitação).
Você pode retrair: 408/429/5xx/ 425/499/504 (com backoff + jitter).
Idempotidade: Para 'POST', inclua 'Idempotency-Key' (UUIDv4).
Devolva 409 s 'hint: «Use same Idempotency-Key or GET status» ao conflito de execução.
Adicione 'Idempotency-Replay: true' ao recuperar o resultado salvo.
HTTP/1.1 429 Too Many Requests
Retry-After: 3
RateLimit-Limit: 50
RateLimit-Remaining: 0
RateLimit-Reset: 1730641030
6) Validação de entrada: estrutura de erros de campo
Para 400/422, use um conjunto de erros de campo:json
{
"type": "https://errors.example.com/validation",
"title": "Validation failed",
"status": 422,
"code": "VALIDATION_ERROR",
"trace_id": "01HX4...XYZ",
"errors": [
{"field": "amount", "rule": "min", "message": "Must be >= 10"},
{"field": "currency", "rule": "enum", "message": "Unsupported currency"}
]
}
7) Fracassos parciais (batch/partial failure)
Não esconda um erro dentro de 200 sem estrutura. Devolva 207 Multi-Status ou 200 com uma matriz de resultados onde cada tarefa tenha o seu status:json
{
"status": "partial",
"succeeded": 8,
"failed": 2,
"results": [
{"id": "op1", "status": 201},
{"id": "op2", "status": 422, "error": {"code":"VALIDATION_ERROR","detail":"..."}}
]
}
8) Paginação e respostas «em branco»
Colecção vazia - 200 s 'items: []', não 404.
O fim da página é 'next _ page _ tocen' ausente.
O token errado é 400 s 'código: PAGINATION _ CURSOR _ INVALID'.
9) Webhooks: entrega confiável
Assine eventos (HMAC) e verifique antes do processamento.
A resposta para o processamento bem-sucedido é 2xx (melhor que 204).
Falhas temporárias do destinatário - 5xx; o remetente repete (backoff exponencial, jitter).
Deduplicar por 'event _ id' e salvar o resultado (idempotent consumer).
Payload inválido - 400/422 sem repetição.
10) Conformidade com protocolos (gRPC/GraphQL)
gRPC → HTTP:- `INVALID_ARGUMENT` → 400
- `UNAUTHENTICATED` → 401
- `PERMISSION_DENIED` → 403
- `NOT_FOUND` → 404
- `ALREADY_EXISTS` → 409
- `FAILED_PRECONDITION` → 412/422
- `RESOURCE_EXHAUSTED` → 429
- `ABORTED` → 409
- `UNAVAILABLE` → 503
- `DEADLINE_EXCEEDED` → 504
json
{
"data": { "createPayment": null },
"errors": [{
"message": "Forbidden",
"extensions": { "code": "FORBIDDEN", "status": 403, "trace_id": "..." },
"path": ["createPayment"]
}]
}
Não é recomendado usar o código HTTP apropriado para erros críticos.
11) Cabeçalhos e dicas ao cliente
'Retry-After' - segundos/data NTTR (429/503/425/408).
«Warning» é uma degradação suave ou deprekate («199 - Função X is deprecated»).
`Deprecation`, `Sunset`, `Link: <...>; rel = «deprecation» '- para desligamento controlado.
'Problem-Tipo' é um rápido routing de erros no cliente.
'X-Trace-Id '/' Correlation-Id' - liga logs/trailers.
12) Segurança das mensagens
Não repita os segredos de entrada (tokens/assinaturas) no corpo da resposta.
Disfarce o PAN/PII ('1234').
Para 401/403 - Não mostre qual atributo falhou.
Para 404, em vez de «resource exists out not yurs» - apenas 404.
13) Observabilidade de erros
Métricas:- `http_errors_total{status, route, tenant}`
- 'Error _ classes _ total\código 03' (por 'código' do corpo)
- participação 429, 5xx; 'p95 '/' p99' latency para respostas erradas separadamente
- 'retry _ after _ secunds _ bucket' é um histograma de dicas de repetição
- Vincule a resposta a «trace _ id», guarde «código», «tipo», «status», «rota», «tenant», sem PII.
- sobe '5xx _ rate> X%' com RPS> N;
- crescimento 429 em rotas críticas;
- 'timeout/504' nas dependências;
- frequentes 409/idempotidade → um sinal de corrida.
14) Exemplos
14. 1.422 (validação de negócios)
json
{
"type": "https://errors.example.com/payments/limit-exceeded",
"title": "Limit exceeded",
"status": 422,
"code": "PAYMENT_LIMIT_EXCEEDED",
"detail": "Daily withdrawal limit reached for KYC1.",
"hint": "Increase limits after KYC2 or try tomorrow.",
"trace_id": "01J5...XYZ"
}
14. 2.409 (idempotação)
HTTP/1.1 409 Conflict
Idempotency-Replay: true
json
{
"type": "https://errors.example.com/idempotency/replay",
"title": "Duplicate request",
"status": 409,
"code": "IDEMPOTENT_REPLAY",
"detail": "A request with the same Idempotency-Key was already processed.",
"hint": "Reuse the same Idempotency-Key and GET the operation status."
}
14. 3.429 (limites)
json
{
"type":"https://errors.example.com/rate/too-many-requests",
"title":"Too many requests",
"status":429,
"code":"RATE_LIMITED",
"detail":"Per-key rate limit exceeded.",
"hint":"Retry after the time specified in Retry-After header."
}
15) Antipattern
Devolver 200 com o texto do erro corporal.
Misturar diferentes formatos de erro entre serviços.
Revelar pilha/SQL/nomes de tabela/URL interno em 'detail'.
Usar 'mensagem' em vez de 'código '/' tipo' estável.
Devolver 500 em um erro empresarial esperado (por exemplo, «saldo insuficiente»).
Semântica incoerente entre REST/GraphQL/gRPC.
16) Especificidades do iGaming/Finanças
Códigos claros para KYC/AML/sanções: 'KYC _ RECREED', 'KYC _ REVIEW', 'AML _ LOCK', 'SANÇÃO _ BLOCKED'.
Restrições de jurisdição: 451 com formulação segura sem lista.
Transações write em dinheiro: 409/423 em competição e bloqueios, 'hint' com janela de repetição.
Invariantes de limite de jogador: use 422 para violar regras de pagamento responsável.
Auditoria: registros de soluções inalterados (código, hora, acerto, trace _ id).
17) Folha de cheque pró-prontidão
- Padrão de erro de JSON unificado, estável 'tipo '/' código'.
- O mapping HTTP ↔ gRPC/GraphQL negociado e documentado.
- Semântica de retais + 'Retry-After'; idimpotência para write.
- Camuflar PII/segredos; 404 para ocultação de recursos.
- Métricas de erro e alertas; corelação com 'trace _ id'.
- Políticas de deprecação: 'Deprecation', 'Sunset', 'Link'.
- Testes: negativo/fuzz, conflito de versões, queda de dependências, duplo-submit.
- Hyde aos clientes: exemplos de back-offs e processamento 409/422/429/5xx.
18) TL; DR
Normalize um único formato de erro JSON c 'tipo '/' código '/' trace _ id', use códigos HTTP corretos, distinção de validação (400/422), direitos de (401/403/404), conflitos/idempotidade (409) e limites (429). Vamos claramente 'Retry-After' e 'hint', disfarçar dados sensíveis, logar erros com 'trace _ id' e construir alertas de 5xx/429/p99.