From da3cd29314b5ce56633d478b82325fd633904492 Mon Sep 17 00:00:00 2001 From: Osamaali313 Date: Mon, 20 Jul 2026 00:05:18 +0300 Subject: [PATCH] Fix UnboundLocalError in OpenAPI generation for custom response classes In `get_openapi_path`, `status_code` is assigned only inside the branches: if route.status_code is not None: status_code = str(route.status_code) else: response_signature = inspect.signature(current_response_class.__init__) status_code_param = response_signature.parameters.get("status_code") if status_code_param is not None: if isinstance(status_code_param.default, int): status_code = str(status_code_param.default) operation.setdefault("responses", {}).setdefault(status_code, {})["description"] = ... When `route.status_code is None` and the response class's `__init__` has no `status_code` parameter (or its default is not an `int`), `status_code` is never bound, but the following line uses it as a dict key -> `UnboundLocalError`. This is reachable with a common pattern: a custom `response_class` whose `__init__` is `def __init__(self, *args, **kwargs)` (or types `status_code` as `int | None = None`). Because `get_openapi_path` -> `get_openapi` -> `Application.openapi()`, a single such route makes `app.openapi()` raise, taking down `/openapi.json`, `/docs`, and `/redoc` for the whole app. Initialize `status_code` to "200" (FastAPI's default route status) before the branches so it is always bound; the working paths are unchanged. --- fastapi/openapi/utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/fastapi/openapi/utils.py b/fastapi/openapi/utils.py index 2e0aca118..590459cb5 100644 --- a/fastapi/openapi/utils.py +++ b/fastapi/openapi/utils.py @@ -337,6 +337,7 @@ def get_openapi_path( ) callbacks[callback.name] = {callback.path: cb_path} operation["callbacks"] = callbacks + status_code = "200" if route.status_code is not None: status_code = str(route.status_code) else: