GH GambleHub

Procesamiento de errores y códigos de estado

1) Por qué estandarizar errores

El contrato de error único acelera la depuración de los clientes, reduce los falsos retratos y hace reproducible el RCA. Buen sistema:
  • codifica previsiblemente el tipo de problema,
  • da al cliente pistas válidas (qué hacer a continuación),
  • protege contra la fuga de piezas internas,
  • compatible con retraídas e idempotencia.

2) Principios de diseño

1. Un esquema de errores para todos los servicios (NAT/GraphQL/gRPC/webhooks).
2. Una clara semántica de retraídas: qué códigos retraer, cuáles no.
3. Fail-closed en las operaciones de escritura: mejor 4xx/5xx que la inconsistencia silenciosa.
4. Sin fugas: no revelar SQL, pilas, confecciones, ID interno.
5. Rastreo: siempre devuelve 'trace _ id '/' correlation _ id'.
6. Localización de mensajes - opcional, pero los códigos y 'reason' se mantienen estables.


3) Formato único (Detalles del problema/JSON)

Formato básico recomendado (compatible 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"
}
}
Explicaciones:
  • 'type' es un identificador de URL estable de clase de error.
  • 'code' es un código de máquina corto de un dominio (estable entre lanzamientos).
  • 'hint' - qué hacer al cliente (repetir, actualizar el token, cambiar los parámetros).
  • 'meta' - detalles seguros (sin secretos y PII).

4) Mapa de códigos de estado (conjunto mínimo)

Autenticación/autorización

400 Bad Request - validación estructural/esquema.
401 Unauthorized - No/No es un token invisible. Agregue 'WWW-Authenticate'.
403 Forbidden - autenticado, pero no se han denegado derechos/políticas.
404 Not Found - Enmascara la existencia de un recurso si no hay derechos.
409 Conflict es un conflicto de versiones/estados (bloqueo optimístico, idempotencia).
451 Unavailable For Legal Reasons - Bloque de cumplimiento/jurisdicción.

Límites y protección

408 Request Timeout: el cliente envía el cuerpo demasiado lentamente.
409/425 Too Early - Prohibición de repetición temprana en el 0-RTT/TLS 1. 3.
429 Too Many Requests - con 'Retry-After' y política de límites.
499 Client Closed Request - (en el perímetro/NGINX) el cliente rompió la conexión.

Datos y reglas de negocio

422 Contenido no procesable: la validación empresarial ha pasado el esquema, pero el significado es incorrecto.
423 Bloqueado: el recurso está bloqueado (revisión KYC, AML freeze).
409 Conflict - Doble envío, carrera, límite de estado (por ejemplo, «ya en proceso»).
410 Gone - Endpoint/recurso eliminado (deprechate completado).

Del servidor

500 Error de servidor interno: error desconocido; no revelar detalles.
502 Bad Gateway: la dependencia devolvió el error/proxy.
503 Service Unavailable - degradación/trabajo planificado; añadir 'Retry-After'.
504 Gateway Timeout - Timaut de dependencias.

💡 Regla: operaciones de escritura cuando se cuestiona → 409 (conflicto) o 503 (repetición posterior), no 200.

5) Semántica de retraídas e idempotencia

No se puede retractar: 400/ 401/403/404/422 (a menos que el cliente haya modificado la solicitud).
Se puede retractar: 408/429/5xx/ 425/499/504 (con backoff + jitter).
Idempotencia: para 'POST', incluye 'Idempotency-Key' (UUIDv4).

En el conflicto de repetición, devuelva 409 con 'hint: "Use same Idempotency-Key or GET status" ".
Añade 'Idempotency-Replay: true' cuando devuelvas el resultado guardado.

Headers de ejemplo en 429:

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

6) Validación de entrada: estructura de errores de campo

Para 400/422, utilice la matriz de errores 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) Fallas parciales (batch/falla parcial)

En los endpoints de batch, no esconda errores dentro de 200 sin estructura. Devuelva 207 Multi-Status o 200 con la matriz de resultados donde cada trabajo tiene su estado:
json
{
"status": "partial",
"succeeded": 8,
"failed": 2,
"results": [
{"id": "op1", "status": 201},
{"id": "op2", "status": 422, "error": {"code":"VALIDATION_ERROR","detail":"..."}}
]
}

8) Paginación y respuestas «vacías»

Colección vacía - 200 s 'items: []', no 404.
El final de la página es 'next _ page _ token'.
Token incorrecto - 400 s 'code: PAGINATION_CURSOR_INVALID'.


9) Webhooks: entrega confiable

Firme eventos (HMAC) y compruebe antes del procesamiento.
La respuesta a un procesamiento exitoso es 2xx (mejor que 204).
Fallas temporales del destinatario - 5xx; el remitente repite (backoff exponencial, jitter).
Deduplicar por 'event _ id' y guardar el resultado (consumidor idempotent).
Payload no válido - 400/422 sin repeticiones.


10) Cumplimiento de 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: siempre 200 en el nivel de transporte es permisible, pero coloque los errores en 'errors []' y duplique en encabezados/extensiones:
json
{
"data": { "createPayment": null },
"errors": [{
"message": "Forbidden",
"extensions": { "code": "FORBIDDEN", "status": 403, "trace_id": "..." },
"path": ["createPayment"]
}]
}

Se recomienda no utilizar 200 para errores críticos, sino el código HTTP correspondiente.


11) Encabezados y consejos al cliente

'Retry-After' - segundos/NTTR-fecha (429/503/425/408).
'Warning' es una degradación suave o deprechate («199 - Feature X is deprecated»).
`Deprecation`, `Sunset`, `Link: <...>; rel = "deprecation" "- para desconexión controlada.
'Problem-Type' (personalizado) - Enrutamiento rápido de errores en el cliente.
'X-Trace-Id '/' Correlation-Id' - enlaza logs/tracks.


12) Seguridad de mensajes

No repita los secretos de entrada (tokens/firmas) en el cuerpo de respuesta.
Enmascarar PAN/PII ('1234').
Para 401/403 - no revele exactamente qué atributo falló.
Para 404, en lugar de «resource exists but not yours» - simplemente 404.


13) Observabilidad de errores

Métricas:
  • `http_errors_total{status, route, tenant}`
  • 'error _ classes _ total {code}' (por 'código' del cuerpo)
  • share 429, 5xx; 'p95 '/' p99' latency para respuestas erróneas por separado
  • 'retry _ after _ seconds _ bucket' - un histograma de consejos de repetición
Logs/Tracks:
  • asocie la respuesta a 'trace _ id', almacene 'code', 'type', 'status', 'route', 'tenant', sin PII.
Alertas:
  • el estallido '5xx _ rate> X%' en RPS> N;
  • crecimiento de 429 en rutas críticas;
  • 'timeout/504' en dependencias;
  • 409/idempotencia frecuentes → signo de carreras.

14) Ejemplos

14. 1.422 (validación de negocios)

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


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 (límites)

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 con texto de error en el cuerpo.
Mezclar diferentes formatos de error entre servicios.
Revelar pila/SQL/nombres de tabla/URL internas en 'detail'.
Utilice 'message' en lugar de 'code '/' type' estable.
Devuelve 500 en un error de negocio esperado (por ejemplo, «el balance es insuficiente»).
Semántica inconsistente entre NAT/GraphQL/gRPC.


16) Especificidad de iGaming/finanzas

Códigos claros para KYC/AML/sanciones: 'KYC _ REQUIRED', 'KYC _ REVIEW', 'AML _ LOCK', 'SANCTION _ BLOCKED'.
Restricciones jurisdiccionales: 451 con una formulación segura sin especificar listas.
Operaciones de escritura en efectivo: 409/423 cuando se compite y se bloquea, 'hint' con ventana de repetición.
Invariantes de límite de jugador: use 422 para violar las reglas de pago responsable.
Auditoría: registros de soluciones inmutables (código, tiempo, actor, trace_id).


17) Lista de comprobación de disponibilidad

  • Circuito único de errores JSON, estable 'type '/' code'.
  • El mapping HTTP ↔ gRPC/GraphQL está negociado y documentado.
  • Semántica Retraye + 'Retry-After'; idempotencia para escribir.
  • Enmascarar PII/secretos; 404 para ocultar recursos.
  • Métricas de errores y alertas; Corelación con 'trace _ id'.
  • Políticos de deprechate: 'Deprecation', 'Sunset', 'Link'.
  • Pruebas: negative/fuzz, conflicto de versiones, caída de dependencias, doble-submit.
  • Hyde a los clientes: ejemplos de back-offs y procesamiento 409/422/429/5xx.

18) TL; DR

Estandarizar un formato de error JSON único c 'type '/' code '/' trace _ id', utilizar códigos HTTP correctos, distinguir validación (400/422), derechos de (401/403/404), conflictos/idempotencia (409) y límites (429). Seamos claros 'Retry-After' e 'hint', enmascara datos sensibles, lógica errores con 'trace _ id' y construya alertas de 5xx/429/p99.

Contact

Póngase en contacto

Escríbanos ante cualquier duda o necesidad de soporte.¡Siempre estamos listos para ayudarle!

Iniciar integración

El Email es obligatorio. Telegram o WhatsApp — opcionales.

Su nombre opcional
Email opcional
Asunto opcional
Mensaje opcional
Telegram opcional
@
Si indica Telegram, también le responderemos allí además del Email.
WhatsApp opcional
Formato: +código de país y número (por ejemplo, +34XXXXXXXXX).

Al hacer clic en el botón, usted acepta el tratamiento de sus datos.