GH GambleHub

Traitement des erreurs et codes d'état

1) Pourquoi normaliser les erreurs

Un contrat d'erreur unique accélère le débogage des clients, réduit les fausses retraits et rend RCA reproductible. Bon système :
  • Codage prévisible du type de problème,
  • donne au client des indices valables (que faire ensuite),
  • protège contre les fuites des pièces internes,
  • compatible avec les retraits et l'idempotence.

2) Principes de conception

1. Un schéma d'erreur pour tous les services (REST/GraphQL/gRPC/webhooks).
2. La sémantique claire des rétrogrades : quels sont les codes à retracer, lesquels ne le sont pas.
3. Fail-closed sur les opérations write : Mieux vaut 4xx/5xx que la non-consistance silencieuse.
4. Pas de fuites : ne pas révéler SQL, piles, fligs, ID internes.
5. Trace : retournez toujours 'trace _ id '/' correlation _ id'.
6. Localisation des messages - en option, mais les codes et 'reason' restent stables.


3) Format unique (Détails du problème/JSON)

Format de base recommandé (compatible avec la 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"
}
}
Explications :
  • 'type' est l'URL stable de la classe d'erreur.
  • 'Code 'est un code de domaine machine court (stable entre les versions).
  • 'hint' - Quoi faire au client (répétition, mise à jour du token, modification des paramètres).
  • « meta » - détails sécurisés (pas de secrets et PII).

4) Carte des codes d'état (ensemble minimum)

Authentification/autorisation

400 Bad Request - Validation structurelle/schéma.
401 Non validé - Non/token non validé. Ajoutez 'WWW-Authenticate'.
403 Forbidden - authentifié, mais aucun droit/politique refusé.
404 Not Found - Masquer l'existence d'une ressource en l'absence de droits.
409 Conflict est un conflit de versions/états (lock optimiste, idempotence).
451 Unavailable For Legal Reasons - bloc de conformité/juridiction.

Limites et protection

408 Request Timeout - le client envoie le corps trop lentement.
409/425 Too Early - interdiction de la répétition précoce dans le 0-RTT/TLS 1. 3.
429 Too Many Requests - avec 'Retry-After' et la politique de limite.
499 Client Closed Request - (sur le périmètre/NGINX) le client a rompu la connexion.

Données et règles commerciales

422 Contenu irréductible - la validation d'entreprise a passé le schéma, mais le sens est faux.
423 Locked - ressource bloquée (KYC review, AML freeze).
409 Conflict - Double envoi, course, limite d'état (par exemple, « déjà en cours de traitement »).
410 Gone - endpoint/ressource enlevée (deprecate terminé).

De serveur

500 Internal Server Error - erreur inconnue ; ne pas révéler les détails.
502 Bad Gateway - La dépendance a renvoyé l'erreur/proxy.
503 Service Unavailable - Travaux de dégradation/planification ; ajouter « Retry-After ».
504 Gateway Timeout - temps de dépendance.

💡 Règle : write-operations en cas de doute → 409 (conflit) ou 503 (répétition plus tard), pas 200.

5) La sémantique des rétrogrades et de l'idempotence

Vous ne pouvez pas retracer : 400/ 401/403/404/422 (si le client n'a pas modifié la demande).
Peut être rétracté : 408/429/5xx/ 425/499/504 (avec backoff + jitter).
Idempotence : pour 'POST', activez 'Idempotency-Key' (UUIDv4).

En cas de conflit de réexécution, renvoyez 409 avec 'hint :' Use same Idempotency-Key or GET status '.
Ajoutez 'Idempotency-Replay : true' lorsque vous retournez le résultat enregistré.

Exemple de headers à 429 :

HTTP/1.1 429 Too Many Requests
Retry-After: 3
RateLimit-Limit: 50
RateLimit-Remaining: 0
RateLimit-Reset: 1730641030

6) Validation d'entrée : structure des erreurs de champ

Pour 400/422, utilisez un tableau d'erreurs de champ :
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) Échecs partiels (batch/panne partielle)

Dans les endpoints batch, ne cachez pas les erreurs à l'intérieur de 200 sans structure. Renvoyez 207 Multi-Status ou 200 avec un tableau de résultats où chaque tâche a son propre statut :
json
{
"status": "partial",
"succeeded": 8,
"failed": 2,
"results": [
{"id": "op1", "status": 201},
{"id": "op2", "status": 422, "error": {"code":"VALIDATION_ERROR","detail":"..."}}
]
}

8) Pagination et réponses « vides »

La collection vide est 200 avec 'items : []', pas 404.
La fin de la page est 'next _ page _ token'.
Le jeton incorrect est 400 avec 'code : PAGINATION_CURSOR_INVALID'.


9) Webhooks : livraison fiable

Signez les événements (HMAC) et vérifiez avant le traitement.
La réponse au traitement réussi est 2xx (meilleure que 204).
Échec temporaire du destinataire : 5xx ; l'expéditeur répète (backoff exponentiel, gitter).
Déduplication par 'event _ id' et enregistrement du résultat (idempotent consumer).
Payload non valide est 400/422 sans répétition.


10) Conformité aux protocoles (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 : toujours 200 au niveau du transport est acceptable, mais placez les erreurs dans 'errors []' et dupliquez dans les titres/extensions :
json
{
"data": { "createPayment": null },
"errors": [{
"message": "Forbidden",
"extensions": { "code": "FORBIDDEN", "status": 403, "trace_id": "..." },
"path": ["createPayment"]
}]
}

Il est recommandé d'utiliser le code HTTP correspondant plutôt que 200 pour les erreurs critiques.


11) Titres et conseils au client

« Retry-After » - secondes/NTTR-date (429/503/425/408).
« Warning » est une dégradation douce ou un deprecate (« 199 - Feature X is deprecated »).
`Deprecation`, `Sunset`, `Link: <...>; rel = « déprécation » - pour l'arrêt contrôlé.
« Problème-Type » : Routage rapide des erreurs sur le client.
"X-Trace-Id'/" Correlation-Id" - relie les logs/trajets.


12) Sécurité des messages

Ne répétez pas les secrets d'entrée (jetons/signatures) dans le corps de la réponse.
Masquer le PAN/PII ('1234').
Pour 401/403 - ne pas révéler exactement quel attribut a échoué.
Pour 404, au lieu de « ressources exists but not yours » - juste 404.


13) Observation des erreurs

Métriques :
  • `http_errors_total{status, route, tenant}`
  • 'error _ classes _ total {code} '(par' code 'du corps)
  • proportion 429, 5xx ; 'p95 '/' p99' latency pour les réponses erronées séparément
  • 'retry _ after _ seconds _ bucket' est un histogramme de conseils de répétition
Logs/trajets :
  • associez la réponse à 'trace _ id', gardez' code ',' type ',' status ',' route ',' tenant ', sans PII.
Alert :
  • surbrillance '5xx _ rate> X %' à RPS> N ;
  • une augmentation de 429 sur les itinéraires critiques ;
  • 'timeout/504' chez les dépendances ;
  • fréquentes 409/idempotence → signe de course.

14) Exemples

14. 1 422 (validation d'entreprise)

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 (idempotence)


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) Anti-modèles

Renvoyer 200 avec le texte d'erreur dans le corps.
Mélanger différents formats d'erreur entre les services.
Afficher la pile/SQL/noms de table/URL interne dans 'detail'.
Utiliser 'message' au lieu de 'code '/' type' stable.
Renvoyer 500 en cas d'erreur professionnelle attendue (par exemple, « solde insuffisant »).
Sémantique incohérente entre REST/GraphQL/gRPC.


16) Spécificités d'iGaming/Finance

Codes clairs pour KYC/AML/sanctions : 'KYC _ REQUIRED', 'KYC _ REVIEW', 'AML _ LOCK', 'SANTÉ _ BLOCKED'.
Limites de compétence : 451 avec un libellé sécurisé sans liste.
Opérations d'écriture monétaire : 409/423 en compétition et en blocage, 'hint' avec fenêtre de répétition.
Invariants limites de joueur : utilisez le 422 pour enfreindre les règles de paiement responsable.
Audit : journaux de décision immuables (code, temps, actionneur, trace_id).


17) Chèque-liste prod-prêt

  • Schéma d'erreur JSON unique, stable 'type '/' code'.
  • Mapping HTTP ↔ gRPC/GraphQL est harmonisé et documenté.
  • Sémantique des rétrogrades + « Retry-After » ; idempotence pour write.
  • Masquage des IPI/secrets ; 404 pour cacher les ressources.
  • Métriques d'erreurs et alertes ; corollation avec 'trace _ id'.
  • Politiques de déprécation : 'Deprecation', 'Sunset', 'Link'.
  • Tests : negative/fuzz, conflit de versions, chute des dépendances, double-submit.
  • Hyde aux clients : exemples de back-offs et traitement 409/422/429/5xx.

18) TL; DR

Normalisez le format d'erreur JSON unique c 'type '/' code '/' trace _ id', utilisez des codes HTTP corrects, distinguez la validation (400/422), les droits de (401/403/404), les conflits/idempotentiités (409) et les limites (429). Laissez clair 'Retry-After' et 'hint', masquez les données sensibles, logiez les erreurs avec 'trace _ id'et construisez les alertes à 5xx/429/p99.

Contact

Prendre contact

Contactez-nous pour toute question ou demande d’assistance.Nous sommes toujours prêts à vous aider !

Commencer l’intégration

L’Email est obligatoire. Telegram ou WhatsApp — optionnels.

Votre nom optionnel
Email optionnel
Objet optionnel
Message optionnel
Telegram optionnel
@
Si vous indiquez Telegram — nous vous répondrons aussi là-bas.
WhatsApp optionnel
Format : +code pays et numéro (ex. +33XXXXXXXXX).

En cliquant sur ce bouton, vous acceptez le traitement de vos données.