exlab_wizard.api.errors#
Error envelope helpers + FastAPI exception handlers. Backend Spec §4.6.3.
Every error response across the API uses the §4.6.3 JSON shape:
{
"error": {
"code": "validation_failed",
"message": "Operator field cannot be empty.",
"field": "operator",
"details": { "min_length": 1 },
"trace_id": "abc123def456"
}
}
Required: code (stable string identifier; this is what client code
branches on), message (human-readable). Optional: field
(field-level validation errors), details (free-form structured
detail), trace_id (echoed from the request’s X-Trace-Id header
if present, else server-generated; correlates with the central app log).
The full code enum table is in §4.6.3; ERROR_CODES mirrors
it as a closed string set so adding a new code requires updating both
the spec section and this module in the same change.
Functions
|
Build the §4.6.3 envelope dict. |
|
Build a FastAPI JSONResponse carrying the §4.6.3 envelope. |
|
Return the request's |
Attach the §4.6.3 envelope handlers to a FastAPI app. |
- exlab_wizard.api.errors.build_error_envelope(*, code, message, field=None, details=None, trace_id=None)[source]#
Build the §4.6.3 envelope dict.
codeis validated againstERROR_CODES; an unknown code is replaced with"internal_error"and logged at WARN so the client always gets a known discriminator.
- exlab_wizard.api.errors.error_response(*, request, code, message, status_code, field=None, details=None, extra=None)[source]#
Build a FastAPI JSONResponse carrying the §4.6.3 envelope.
extrais merged into theerrorblock alongside the four standard fields. The setup-incomplete handler uses this to attachstateandmissingper §4.9.2.
- exlab_wizard.api.errors.extract_or_create_trace_id(request)[source]#
Return the request’s
X-Trace-Idheader, else a fresh hex id.Server-generated ids use 12 hex characters of cryptographic randomness (
secrets.token_hex(6)); plenty of bits for log correlation in a single-user desktop app.
- exlab_wizard.api.errors.register_exception_handlers(app)[source]#
Attach the §4.6.3 envelope handlers to a FastAPI app.
Registered in priority order (FastAPI dispatch is most-specific first by
isinstancetree; the order below is exhaustive enough that the order at registration is mostly cosmetic).Each handler is typed against its concrete exception subclass for readability, but Starlette’s
add_exception_handleris typed to accept callables over the baseException– the dispatcher only invokes a handler when the instance matches its registered type, so the per-handler signatures are sound at runtime. We funnel the registrations through_register()so the necessary cast lives in one place.