Documentación pública

06 · Manejo de errores

MAG-06-ERR · Manejo de errores

Los errores también forman parte del contrato.

Toda la operación. Una sola plataforma.


Objetivo del capítulo

Definir el formato oficial de manejo de errores de Roustix.

Un error nunca debe depender del framework, de SQLAlchemy ni del servidor. El cliente siempre recibe una respuesta consistente, independientemente del módulo.

MAG-06 establece el contrato que utilizarán la aplicación web, las integraciones, el SDK oficial y futuros clientes móviles.

Convenciones de códigos: MAG-05 · §10 Errores.


1 · Filosofía

Un error debe responder tres preguntas:

  1. ¿Qué ocurrió?error.code
  2. ¿Por qué ocurrió?message + details
  3. ¿Qué puede hacer el desarrollador ahora? → HTTP status + código estable

Nunca debe exponer detalles internos del servidor.


2 · Formato oficial

Todas las respuestas de error utilizan exactamente la misma estructura:

{
  "error": {
    "code": "RESOURCE_NOT_FOUND",
    "message": "Activo no encontrado",
    "details": {}
  }
}
CampoDescripción
codeCódigo estable para programación · UPPER_SNAKE_CASE
messageMensaje legible en español (MUX)
detailsInformación adicional opcional

El cliente nunca debe interpretar el texto de message. Siempre debe utilizar error.code.

Legacy: muchos endpoints devuelven {"error": "mensaje"} — convergencia planificada hacia este formato.


3 · Códigos HTTP

Roustix utiliza únicamente códigos HTTP estándar.

HTTPUso
200OK
201Recurso creado
204Sin contenido
400Solicitud inválida
401No autenticado
403Sin permisos
404Recurso inexistente
409Conflicto
422Validación
429Rate limit
500Error interno
503Servicio temporalmente no disponible

4 · Catálogo oficial de errores

Todos los códigos siguen MAG-05: UPPER_SNAKE_CASE.

Autenticación

CódigoHTTP típico
INVALID_TOKEN401
TOKEN_EXPIRED401
TOKEN_REVOKED401
LOGIN_FAILED401
USER_DISABLED403
SESSION_EXPIRED401

Permisos

CódigoHTTP típico
PERMISSION_DENIED403
MODULE_NOT_ENABLED403
PLAN_NOT_ALLOWED403
TENANT_SUSPENDED403

Recursos

CódigoHTTP típico
RESOURCE_NOT_FOUND404
RESOURCE_ALREADY_EXISTS409
RESOURCE_CONFLICT409

Validación

CódigoHTTP típico
VALIDATION_ERROR422
INVALID_PARAMETER400
INVALID_REQUEST400

Plataforma

CódigoHTTP típico
INTERNAL_ERROR500
DATABASE_ERROR500
SERVICE_UNAVAILABLE503
RATE_LIMIT_EXCEEDED429

Nuevos códigos → documentar aquí antes de implementar (MAG-05 §13).


5 · Ejemplos

404

{
  "error": {
    "code": "RESOURCE_NOT_FOUND",
    "message": "Activo no encontrado"
  }
}

401

{
  "error": {
    "code": "INVALID_TOKEN",
    "message": "Token inválido"
  }
}

403

{
  "error": {
    "code": "MODULE_NOT_ENABLED",
    "message": "El módulo Inventory no está habilitado para esta empresa"
  }
}

422

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Existen errores de validación",
    "details": {
      "name": [
        "Este campo es obligatorio."
      ]
    }
  }
}

6 · Validaciones

Cuando existen varios errores de validación:

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Hay errores en la solicitud",
    "details": {
      "asset_code": [
        "Ya existe."
      ],
      "name": [
        "Campo obligatorio."
      ]
    }
  }
}

El cliente puede mostrar cada error directamente. Claves en detailssnake_case inglés (MAG-05).


7 · Errores multi-tenant

Si un recurso pertenece a otra empresa:

GET /api/v1/maintenance/assets/52

Respuesta: 404 · RESOURCE_NOT_FOUND

Nunca 403 — el recurso no debe revelar su existencia.

MAG-03 · Multi-tenant


8 · Errores internos

Nunca devolver:

  • Stack trace
  • SQL
  • Flask exception
  • SQLAlchemy exception
  • Rutas internas
  • Nombres de tablas
❌ Incorrecto
sqlalchemy.exc.NoResultFound...
✅ Correcto
{ "error": { "code": "INTERNAL_ERROR", "message": "Ha ocurrido un error interno." } }

El detalle completo queda únicamente en los logs de la plataforma.


9 · Correlation ID

Todas las respuestas pueden incluir:

X-Request-Id: 6c1d0d82-b6d8-46db-a5db-924d9d79c06d

El cliente puede enviar su propio UUID; el servidor lo propaga o genera uno.

Si el cliente reporta un problema, soporte localiza exactamente la petición.


10 · Ejemplo completo

Solicitud:

GET /api/v1/maintenance/assets/900
Authorization: Bearer <token>
JWT válido
     ↓
Tenant resuelto
     ↓
Activo inexistente
     ↓
404
{
  "error": {
    "code": "RESOURCE_NOT_FOUND",
    "message": "Activo no encontrado"
  }
}

11 · Errores y auditoría

Todos los errores relevantes quedan registrados en la plataforma.

Se registran:

  • usuario
  • tenant (empresa_id)
  • endpoint
  • código HTTP
  • error.code
  • fecha
  • request_id

Nunca: contraseña · token · datos sensibles


12 · Buenas prácticas

#Regla
1Utilizar siempre error.code
2No analizar el texto de message
3Nunca exponer excepciones internas
4Mantener códigos estables entre versiones
5Registrar errores en auditoría
6Toda respuesta de error sigue el mismo formato
7Documentar nuevos códigos antes de implementarlos

Integradores

  • Reintentar solo 429 y 503 con backoff exponencial
  • No reintentar 4xx excepto 429
  • Incluir X-Request-Id en reportes a soporte

13 · Webhooks

Las respuestas de verificación de endpoint webhook usan el mismo formato error. Ver MAG-08.


Filosofía del capítulo

Los errores también son una interfaz. Un contrato consistente permite que personas, SDKs e integraciones reaccionen de forma predecible, independientemente del módulo o de la implementación interna.

MAG-06 convierte el manejo de errores en parte del contrato público de Roustix, garantizando estabilidad para todos los clientes de la API.