Skip to content
Latchkey

FastAPI "AttributeError: 'FieldInfo' object has no attribute" in CI

Code that introspected Pydantic v1 field objects breaks on v2, where fields are FieldInfo instances with different attributes. Accessing a v1 attribute like .outer_type_ or iterating __fields__ the old way raises AttributeError.

What this error means

A test or serializer fails with "AttributeError: 'FieldInfo' object has no attribute 'outer_type_'" or similar when introspecting model fields after upgrading to Pydantic v2.

python
AttributeError: 'FieldInfo' object has no attribute 'outer_type_'

Common causes

Reading v1 field internals on a v2 model

Pydantic v2 replaced ModelField with FieldInfo; attributes like outer_type_, required, or field_info no longer exist in the old shape.

Iterating __fields__ with v1 assumptions

Custom code walks Model.__fields__ expecting v1 objects, but v2 exposes fields via model_fields with a different structure.

How to fix it

Use the v2 field API

  1. Read fields from Model.model_fields, which maps names to FieldInfo.
  2. Get the annotation from field.annotation instead of outer_type_.
  3. Check requiredness with field.is_required().
app/introspect.py
for name, field in User.model_fields.items():
    annotation = field.annotation
    required = field.is_required()

Isolate introspection behind a version shim

If you must support both majors during migration, branch on the Pydantic version and keep the v2 path primary.

app/introspect.py
import pydantic

if pydantic.VERSION.startswith("2"):
    fields = User.model_fields
else:
    fields = User.__fields__

How to prevent it

  • Use model_fields and FieldInfo attributes on Pydantic v2.
  • Avoid reaching into private v1 field internals.
  • Lock the Pydantic major so introspection code sees one API.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →