From 203bba81fbabcd743a2ebf39f440777eef05ef94 Mon Sep 17 00:00:00 2001 From: Anto Subash Date: Mon, 25 May 2026 22:30:12 +0200 Subject: [PATCH 1/2] fix(hosting): render Inertia error page for RequestValidationError (#170) When a browser navigates to a route with an invalid UUID path parameter, FastAPI raises RequestValidationError which was not handled by the framework exception handlers, resulting in raw JSON instead of a styled Inertia error page. Add a RequestValidationError handler that checks the Accept header: - Browser requests (text/html) get a friendly 422 Inertia error page - API/JSON clients get the standard validation detail response --- .../simple_module_hosting/_error_handlers.py | 13 +++++++++++++ .../hosting/simple_module_hosting/_phase_helpers.py | 3 +++ 2 files changed, 16 insertions(+) diff --git a/framework/hosting/simple_module_hosting/_error_handlers.py b/framework/hosting/simple_module_hosting/_error_handlers.py index 6e2092ee..fee6317c 100644 --- a/framework/hosting/simple_module_hosting/_error_handlers.py +++ b/framework/hosting/simple_module_hosting/_error_handlers.py @@ -4,6 +4,7 @@ import logging +from fastapi.exceptions import RequestValidationError from fastapi.responses import JSONResponse from inertia import ( Inertia, @@ -49,6 +50,18 @@ async def not_found_error_handler(request: Request, exc: NotFoundError) -> Respo return await render_error_page(request, 404, str(exc)) +async def request_validation_error_handler( + request: Request, exc: RequestValidationError +) -> Response: + """Return an Inertia error page for browser requests with invalid params.""" + accept = request.headers.get("accept", "") + if "text/html" in accept: + return await render_error_page( + request, 422, "The requested URL contains invalid parameters." + ) + return JSONResponse(status_code=422, content={"detail": exc.errors()}) + + async def unhandled_exception_handler(request: Request, exc: Exception) -> Response: logger.exception("Unhandled exception: %s", exc) return await render_error_page(request, 500, "") diff --git a/framework/hosting/simple_module_hosting/_phase_helpers.py b/framework/hosting/simple_module_hosting/_phase_helpers.py index 743c3440..888337a5 100644 --- a/framework/hosting/simple_module_hosting/_phase_helpers.py +++ b/framework/hosting/simple_module_hosting/_phase_helpers.py @@ -12,6 +12,7 @@ from typing import TYPE_CHECKING from fastapi import APIRouter, FastAPI +from fastapi.exceptions import RequestValidationError from fastapi.routing import APIRoute from fastapi.staticfiles import StaticFiles from inertia import ( @@ -26,6 +27,7 @@ from simple_module_hosting._error_handlers import ( http_exception_handler, not_found_error_handler, + request_validation_error_handler, unhandled_exception_handler, ) from simple_module_hosting.i18n_middleware import LocaleMiddleware @@ -53,6 +55,7 @@ def register_exception_handlers(app: FastAPI, modules: list) -> None: ) app.add_exception_handler(HTTPException, http_exception_handler) app.add_exception_handler(NotFoundError, not_found_error_handler) + app.add_exception_handler(RequestValidationError, request_validation_error_handler) app.add_exception_handler(Exception, unhandled_exception_handler) for mod in modules: mod.register_exception_handlers(app) From ed5e8359c8a639d7def9a78b128a3f54140fd3e8 Mon Sep 17 00:00:00 2001 From: Anto Subash Date: Mon, 25 May 2026 22:45:06 +0200 Subject: [PATCH 2/2] fix(hosting): use jsonable_encoder for validation error serialization RequestValidationError.errors() can contain non-JSON-serializable objects (e.g., ValueError instances in the ctx field). Use FastAPI's jsonable_encoder to safely serialize the error details in the JSON response path of request_validation_error_handler. --- framework/hosting/simple_module_hosting/_error_handlers.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/framework/hosting/simple_module_hosting/_error_handlers.py b/framework/hosting/simple_module_hosting/_error_handlers.py index fee6317c..cf861a77 100644 --- a/framework/hosting/simple_module_hosting/_error_handlers.py +++ b/framework/hosting/simple_module_hosting/_error_handlers.py @@ -4,6 +4,7 @@ import logging +from fastapi.encoders import jsonable_encoder from fastapi.exceptions import RequestValidationError from fastapi.responses import JSONResponse from inertia import ( @@ -59,7 +60,7 @@ async def request_validation_error_handler( return await render_error_page( request, 422, "The requested URL contains invalid parameters." ) - return JSONResponse(status_code=422, content={"detail": exc.errors()}) + return JSONResponse(status_code=422, content={"detail": jsonable_encoder(exc.errors())}) async def unhandled_exception_handler(request: Request, exc: Exception) -> Response: