app.middlewares.error_handler module

Catch-all error handler that keeps CORS headers on 500 responses.

Starlette builds its middleware stack with ServerErrorMiddleware as the outermost layer, sitting above the user-added CORSMiddleware. So an unhandled exception (a real 500) is rendered by ServerErrorMiddleware and never passes back through CORSMiddleware - the response ships without Access-Control-Allow-Origin. The browser then blocks the cross-origin response and the dashboard shows a bare “Network Error” instead of the real status/message (see reference_network_error_means_500).

This pure-ASGI middleware is installed inside CORSMiddleware (CORS is added last in app/main.py so it stays outermost). It converts any unhandled exception into a JSON 500 within the stack, so the response flows back out through CORSMiddleware and gets its CORS headers. The traceback is still logged (and forwarded to Sentry) so observability is unchanged.

HTTPException and its subclasses never reach here - Starlette’s ExceptionMiddleware (also inside CORS) already turns them into proper 4xx responses with CORS headers. Only genuine, unhandled errors are caught.

class app.middlewares.error_handler.CatchUnhandledErrorsMiddleware(app)[source]

Bases: object

Render unhandled exceptions as a JSON 500 from inside the stack.