Gestione degli errori e codici di stato
1) Perché standardizzare gli errori
Un unico contratto di errore velocizza il debug dei client, riduce i falsi retrai e rende RCA ripetibile. Buon sistema:- codifica prevedibilmente il tipo di problema,
- fornisce suggerimenti validi al cliente (cosa fare dopo),
- protegge dalla fuoriuscita delle parti interne,
- compatibile con i retrai e l'idipotenza.
2) Principi di progettazione
1. Uno schema di errori per tutti i servizi (REST/GraphQL/gRPC/webhooks).
2. La semantica chiara dei retrai, quali codici ritrasferire, quali no.
3. Fail-closed nelle operazioni write: meglio 4xx/5xx che non essere silenzioso.
4. Nessuna fuoriuscita: non esporre SQL, stack, confighi, ID interni.
5. Traccia: restituisci sempre «trace _ id »/« correlation _ id».
6. La localizzazione dei messaggi è opzionale, ma i codici e «reason» rimangono stabili.
3) Formato unico (Problem Details/JSON)
Formato base consigliato (compatibile con 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"
}
}
Spiegazioni:
- 'type' è un URL stabile della classe di errori.
- «code» è un breve codice di dominio automatico (stabile tra le release).
- «hint» - cosa fare al cliente (ripetizione, aggiornamento del token, modifica delle impostazioni).
- «meta» è un dettaglio sicuro (senza segreti né PII).
4) Mappa dei codici di stato (set minimo)
Autenticazione/autorizzazione
400 Bad Recest - convalida strutturale/schema.
401 Unauthorized - no/nevaliden token. Aggiungi «WWW-Authenticate».
403 Forbidden - autenticato, ma nessun diritto/criterio negato.
404 Not Found - Maschera l'esistenza della risorsa in assenza di diritti.
409 Conflict - conflitto di versioni/stati (ottimistica lock, idampotenza).
451 Unavailable For Legale Reasons è un blocco di conformità/giurisdizione.
Limiti e protezione
408 Richiest Timeout - Il cliente invia troppo lentamente il corpo.
409/425 Too Early - Divieto di ripetizione precoce in 0-RTT/TLS 1. 3.
429 Too Many Recests - con Retry-After e criteri di limite.
499 Client Closed Sollest - (perimetro/NGINX) il client ha interrotto la connessione.
Dati e regole aziendali
422 Unprocessable Content - La validazione aziendale ha superato lo schema, ma il significato non è corretto.
423 Locked - Risorsa bloccata (KYC review, AML freeze).
409 Conflict - doppia spedizione, corsa, limite di stato (ad esempio, «già in lavorazione»).
410 Gone - endpoint/risorsa rimossa (deprecato completato).
Server
500 Internal Server Errore sconosciuto Non rivelare i dettagli.
502 Bad Gateway - La dipendenza ha restituito un errore/proxy.
503 Service Unavailable - degrado/lavoro pianificato aggiungere'Retry-After '.
504 Gateway Timeout - timeout delle dipendenze.
5) Semantica di retraici e idampotenza
Non è possibile ritrarre 400/ 401/403/404/422 (se il client non ha modificato la richiesta).
Puoi ritrarre 408/429/5xx/ 425/499/504 (con backoff + jitter).
Idempotenza: per «POST», attivare «Idempotency-Key» (UUIDv4).
Restituisci 409 con'hint ': Use same Idempotency-Key or GET status'.
Aggiungi «Idempotency-Replay: true» quando restituisci il risultato salvato.
HTTP/1.1 429 Too Many Requests
Retry-After: 3
RateLimit-Limit: 50
RateLimit-Remaining: 0
RateLimit-Reset: 1730641030
6) Convalida accesso: struttura degli errori di campo
Per 400/422, utilizzare un array di errori di 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) Fallimenti parziali (batch/partial failure)
Gli endpoint non nascondono errori all'interno di 200 senza struttura. Restituire 207 Multi-Status o 200 con un array di risultati in cui ogni operazione ha lo stato:json
{
"status": "partial",
"succeeded": 8,
"failed": 2,
"results": [
{"id": "op1", "status": 201},
{"id": "op2", "status": 422, "error": {"code":"VALIDATION_ERROR","detail":"..."}}
]
}
8) Paginazione e risposte «vuote»
Raccolta vuota - 200 con «items: []», non 404.
L'estremità della pagina è 'next _ page _ token'.
Token non corretto: 400 con'code: PAGINATION _ CURSOR _ INVALID '.
9) Webhooks: consegna affidabile
Firmare eventi (HMAC) e controllare prima dell'elaborazione.
La risposta all'elaborazione è 2xx (meglio 204).
Guasti temporanei del destinatario: 5xx il mittente ripete (backoff esponenziale, jitter).
Deduplicazione per «event _ id» e salvataggio dei risultati (idempotent consumer).
payload non valido: 400/422 senza ripetizione.
10) Conformità ai protocolli (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"]
}]
}
Si consiglia di utilizzare il codice HTTP corrispondente non 200 per gli errori critici.
11) Intestazioni e suggerimenti al cliente
Retry-After - secondi/data NTCR (429/503/425/408).
«Warning» è un degrado morbido o deprecato («199 - Feature X is deprecated»).
`Deprecation`, `Sunset`, `Link: <...>; rel = «deprecation» - per la disattivazione guidata.
«Profem-Type» - Routing rapido degli errori sul client.
X-Trace-Id/« Correlation-ID »- Collega i loghi/trailer.
12) Protezione dei messaggi
Non ripetere i segreti di input (token/firma) nel corpo della risposta.
Maschera PAN/PII ('1234').
Per 401/403 - Non rivelare quale attributo ha fallito.
Per il 404 invece di «resource executs out not yours» è solo 404.
13) Osservazione degli errori
Metriche:- `http_errors_total{status, route, tenant}`
- 'errore _ classes _ total {code} '(in' code ', dal corpo)
- quota 429, 5xx; «p95 »/« p99» latency per risposte errate separatamente
- «retry _ after _ seconds _ bucket» è un istogramma di suggerimenti di ripetizione
- collegare la risposta a «trace _ id», memorizzare «code», «type», «status», «route», «tenant», senza PII.
- spunta '5xx _ rate> X%' con RPS> N;
- crescita 429 su percorsi critici;
- timeout/504 per le dipendenze;
- spesso 409/idampotenza è un segno di corsa.
14) Esempi
14. 1.422 (validazione aziendale)
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 (idampotenza)
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 (limiti)
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
Restituisci 200 con il testo dell'errore nel corpo.
Mescola diversi formati di errore tra i servizi.
Espandi stack/SQL/nomi tabella/URL interni in «detail».
Usa "messagge'invece di" code "/" type "stabile.
Restituire 500 in caso di errore aziendale previsto (ad esempio, «bilanciamento insufficiente»).
Una semantica incoerente tra le due.
16) Specificità iGaming/finanza
Codici chiari per KYC/AML/sanzioni: 'KYC _ RICHIRED', 'KYC _ REVIEW', 'AML _ LOCK', 'SANCTION _ BLOCKED'.
Restrizioni di giurisdizione: 451 con formulazione sicura senza elenchi.
Transazioni write in denaro: 409/423 con concorrenza e blocchi, 'hint'con finestra di ripetizione.
Invarianti dei limiti del giocatore: usa 422 per violare le regole di pagamento responsabile.
Controllo: registri di soluzioni invariati (codice, ora, attrezzo, trace _ id).
17) Assegno-foglio prod-pronto
- Schema unico di errore JSON stabile 'type '/' code'.
- Il mapping HTTP è stato concordato e documentato.
- Semantica dei retrai + «Retry-After»; Idipotenza per write.
- Mascherare PII/segreti; 404 per nascondere le risorse.
- Metriche di errori e alert; corellazione con'trace _ id '.
- Criteri di deprecazione: Deprecation, Sunset, Link.
- Test: negative/fuzz, conflitti di versione, calo delle dipendenze, doppio-sottomit.
- Hyde ai clienti: esempi di back-off e trattamento 409/422/429/5xx.
18) TL; DR
Standardizzare un unico formato JSON con «type »/« code »/« trace _ id», utilizzare i codici HTTP corretti, distinguere tra convalida (400/422), diritti (401/403/404), conflitti/idampotenza (409) e limiti (429). Mettiamo in chiaro «Retry-After» e «hint», mascherate i dati sensibili, regolate gli errori con «trace _ id» e costruite gli alert da 5xx/429/p99.