GH GambleHub

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.

💡 Regola: operazioni write in caso di dubbio 409 (conflitto) o 503 (ripetizione successiva), non 200.

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.

Esempio di headers a 429:

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
GraphQL: sempre 200 a livello di trasporto, ma inserisci gli errori in «errors []» e duplicati in intestazioni/estensioni:
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
Logi/roulotte:
  • collegare la risposta a «trace _ id», memorizzare «code», «type», «status», «route», «tenant», senza PII.
Alert:
  • 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.

Contact

Mettiti in contatto

Scrivici per qualsiasi domanda o richiesta di supporto.Siamo sempre pronti ad aiutarti!

Avvia integrazione

L’Email è obbligatoria. Telegram o WhatsApp — opzionali.

Il tuo nome opzionale
Email opzionale
Oggetto opzionale
Messaggio opzionale
Telegram opzionale
@
Se indichi Telegram — ti risponderemo anche lì, oltre che via Email.
WhatsApp opzionale
Formato: +prefisso internazionale e numero (ad es. +39XXXXXXXXX).

Cliccando sul pulsante, acconsenti al trattamento dei dati.