diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index aceca6a1d3..2f7a35c9e3 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -245,9 +245,22 @@ def get_typed_signature(call: Callable[..., Any]) -> inspect.Signature: def get_typed_annotation(annotation: Any, globalns: dict[str, Any]) -> Any: if isinstance(annotation, str): annotation = ForwardRef(annotation) - annotation = evaluate_forwardref(annotation, globalns, globalns) + if isinstance(annotation, ForwardRef): + annotation = evaluate_forwardref(annotation, globalns, globalns) # ty: ignore[deprecated] if annotation is type(None): return None + # Resolve any ForwardRef inside the first argument of Annotated. + # Python automatically wraps string args in ForwardRef, e.g.: + # Annotated["Potato", Depends(get_potato)] + # becomes Annotated[ForwardRef("Potato"), Depends(get_potato)] at runtime. + # Without this, FastAPI never sees the resolved type and treats the + # parameter as Any, producing an incorrect OpenAPI schema. + if get_origin(annotation) is Annotated: + args = get_args(annotation) + first_arg = args[0] + if isinstance(first_arg, (str, ForwardRef)): + resolved_first = get_typed_annotation(first_arg, globalns) + annotation = Annotated[tuple([resolved_first] + list(args[1:]))] return annotation