GH GambleHub

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.

💡 Regra: operações write em dúvida → 409 (conflito) ou 503 (repetição posterior), não 200.

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.

Exemplo de headers a 429:

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
GraphQL: sempre 200 no nível de transporte, mas coloque os erros em 'errors []' e duplique em cabeçalhos/extensões:
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
Logs/trailers:
  • Vincule a resposta a «trace _ id», guarde «código», «tipo», «status», «rota», «tenant», sem PII.
Alerts:
  • 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.

Contact

Entrar em contacto

Contacte-nos para qualquer questão ou necessidade de apoio.Estamos sempre prontos para ajudar!

Iniciar integração

O Email é obrigatório. Telegram ou WhatsApp — opcionais.

O seu nome opcional
Email opcional
Assunto opcional
Mensagem opcional
Telegram opcional
@
Se indicar Telegram — responderemos também por lá.
WhatsApp opcional
Formato: +indicativo e número (ex.: +351XXXXXXXXX).

Ao clicar, concorda com o tratamento dos seus dados.