From fb47ecee7f14aa47b45daecfb130c94cc96f9dcb Mon Sep 17 00:00:00 2001 From: Richard Bowman Date: Mon, 3 Aug 2026 15:02:28 +0100 Subject: [PATCH] Add a catch-all error handler that serialises exceptions to ProblemDetails format. Unfortunately this does not do anything helpful with logging. --- src/labthings_fastapi/server/__init__.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/labthings_fastapi/server/__init__.py b/src/labthings_fastapi/server/__init__.py index f29991a3..bc4f1ce4 100644 --- a/src/labthings_fastapi/server/__init__.py +++ b/src/labthings_fastapi/server/__init__.py @@ -33,6 +33,7 @@ # `_thing_servers` is used as a global from `ThingServer.__init__` from labthings_fastapi.outputs import blob +from labthings_fastapi.problem_details import ProblemDetails from labthings_fastapi.server.config_model import ( ThingsConfig, ThingServerConfig, @@ -245,6 +246,21 @@ def _set_url_for_middleware(self) -> None: def _add_exception_handlers(self) -> None: """Add exception handlers to the FastAPI application.""" + @self.app.exception_handler(Exception) + async def exceptions_to_problemdetails( + _request: Request, exc: Exception + ) -> JSONResponse: + """Handle all exceptions by returning a ProblemDetails object. + + By default, this does not expose stack traces or line numbers. + + :param _request: the request that started the code that failed. + :param exc: the error that occurred. + :return: a response containing a ProblemDetails object. + """ + pd = ProblemDetails.from_exception(exc) + return JSONResponse(pd.model_dump(), status_code=pd.status or 500) + @self.app.exception_handler(GlobalLockBusyError) async def global_lock_exception_handler( _request: Request, exc: GlobalLockBusyError