From 62d3a23f0911ebdd5e9d53f69068d1a1a943ee31 Mon Sep 17 00:00:00 2001 From: AnshMNSoni Date: Mon, 12 Jan 2026 00:16:54 +0530 Subject: [PATCH] Fix forward references inside Annotated dependencies (fixes #13056) --- fastapi/dependencies/utils.py | 12 ++++++++++++ tests/test_annotated_forwardref.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 tests/test_annotated_forwardref.py diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index 45e1ff3ed..e964036b4 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -5,6 +5,7 @@ from collections.abc import Coroutine, Mapping, Sequence from contextlib import AsyncExitStack, contextmanager from copy import copy, deepcopy from dataclasses import dataclass +from typing import get_type_hints from typing import ( Annotated, Any, @@ -270,8 +271,19 @@ def get_dependant( current_scopes = (parent_oauth_scopes or []) + (own_oauth_scopes or []) path_param_names = get_path_param_names(path) endpoint_signature = get_typed_signature(call) + + # Resolve forward references inside Annotated (fix for issue #13056) + try: + type_hints = get_type_hints(call, include_extras=True) + except Exception: + type_hints = {} + signature_params = endpoint_signature.parameters + for param_name, param in signature_params.items(): + # Inject fully resolved Annotated types (including forward refs) + if param_name in type_hints: + param = param.replace(annotation=type_hints[param_name]) is_path_param = param_name in path_param_names param_details = analyze_param( param_name=param_name, diff --git a/tests/test_annotated_forwardref.py b/tests/test_annotated_forwardref.py new file mode 100644 index 000000000..41eeddcf5 --- /dev/null +++ b/tests/test_annotated_forwardref.py @@ -0,0 +1,28 @@ +from __future__ import annotations + +from dataclasses import dataclass +from typing import Annotated + +from fastapi import Depends, FastAPI +from fastapi.testclient import TestClient + + +def test_annotated_forwardref_dependency(): + app = FastAPI() + + def get_item() -> Item: + return Item(name="apple") + + @app.get("/") + def read(item: Annotated[Item, Depends(get_item)]): + return {"name": item.name} + + @dataclass + class Item: + name: str + + client = TestClient(app) + response = client.get("/") + + assert response.status_code == 200 + assert response.json() == {"name": "apple"}