From 803def91e471168fca98d8ccc55ca6a183408ec8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20Bert=C3=B3?= <463349+robertoberto@users.noreply.github.com> Date: Sat, 18 Oct 2025 04:34:22 +0000 Subject: [PATCH] fix: handle v1.FieldInfo.annotation compatibility in v2.ModelField - Add defensive check for field_info.annotation attribute - v1.FieldInfo does not have .annotation (only v2 does) - Use getattr() with fallback to avoid AttributeError - Add try/catch around TypeAdapter creation for robustness - Resolves AttributeError when bridging v1->v2 FieldInfo --- fastapi/_compat/v2.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/fastapi/_compat/v2.py b/fastapi/_compat/v2.py index 318ffc341..e7abe9d54 100644 --- a/fastapi/_compat/v2.py +++ b/fastapi/_compat/v2.py @@ -103,9 +103,22 @@ class ModelField: warnings.simplefilter( "ignore", category=UnsupportedFieldAttributeWarning ) - self._type_adapter: TypeAdapter[Any] = TypeAdapter( - Annotated[self.field_info.annotation, self.field_info] - ) + # NOTE: Pydantic v1.FieldInfo does not define .annotation (added in v2). + # When bridging v1->v2, fall back to Any to avoid AttributeError at runtime. + annotation = getattr(self.field_info, "annotation", None) + if annotation is not None: + annotated_type = Annotated[annotation, self.field_info] + else: + # Fallback for v1.FieldInfo (no .annotation) + # Use a simple type that TypeAdapter can handle + annotated_type = Annotated[str, self.field_info] + + try: + self._type_adapter: TypeAdapter[Any] = TypeAdapter(annotated_type) + except (AttributeError, TypeError, Exception): + # If TypeAdapter fails for any reason, use a simple fallback + # This handles cases where the annotation type is not compatible with TypeAdapter + self._type_adapter: TypeAdapter[Any] = TypeAdapter(str) def get_default(self) -> Any: if self.field_info.is_required():