Skip to main content

Common Import and Type Errors

Most FastAPI errors at startup or during request handling come from Pydantic validation mismatches, circular imports, or missing packages. This lesson covers root-cause diagnosis — not just the error message, but why it happens.

Learning Focus

By the end of this lesson you can: read FastAPI and Pydantic error tracebacks, identify the exact field or import causing the issue, and apply the correct fix.

ImportError: cannot import name X from fastapi

Cause: The symbol moved, was renamed, or never existed in the version you installed.

Diagnose:

python -c "import fastapi; print(fastapi.__version__)"
pip show fastapi | grep Version

Common examples:

ErrorCauseFix
cannot import name 'Annotated' from 'fastapi'Using Python 3.8 without typing backportfrom typing import Annotated (Python 3.9+) or from typing_extensions import Annotated
cannot import name 'pydantic_settings'Separate package since Pydantic v2pip install pydantic-settings
cannot import name 'validator' from 'pydantic'Pydantic v1 API in v2Replace @validator with @field_validator

422 Unprocessable Entity — Reading the Detail

{
"detail": [
{
"type": "missing",
"loc": ["body", "email"],
"msg": "Field required",
"input": {"username": "alice"}
}
]
}
  • loc shows the path: ["body", "email"] means the email field in the request body.
  • type is the Pydantic error code: missing, string_too_short, int_parsing, etc.
  • input is what was actually received.

Diagnose:

curl -s -X POST http://localhost:8000/users/ \
-H "Content-Type: application/json" \
-d '{"username": "alice"}' | python -m json.tool

Pydantic v1 → v2 Migration Errors

v1 CodeError in v2v2 Replacement
class Config: orm_mode = TruePydanticUserErrormodel_config = ConfigDict(from_attributes=True)
@validator("field")PydanticUserError@field_validator("field")
model.dict()AttributeWarningmodel.model_dump()
model.json()Deprecatedmodel.model_dump_json()
schema_extraIgnoredjson_schema_extra in model_config

Circular Import Errors

Symptom: ImportError: cannot import name 'X' from partially initialized module 'app.Y'

Root cause: app.routers.users imports from app.services.users, which imports from app.db.models.user, which imports from app.routers.users.

Fix: Break the cycle with TYPE_CHECKING:

app/services/user_service.py
from __future__ import annotations
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from app.repositories.user_repo import UserRepository # Only for type hints

Or restructure: models → repositories → services → routers (one direction only).

AttributeError: 'coroutine' object has no attribute 'X'

Cause: Called an async function without await.

# ❌ Wrong
user = get_user(db, user_id) # Returns a coroutine, not a User
print(user.username) # AttributeError

# ✅ Correct
user = await get_user(db, user_id)
print(user.username)

RuntimeError: no running event loop

Cause: Calling asyncio.get_event_loop().run_until_complete() inside an async context, or running async code at module import time.

Fix: Never call sync asyncio.run() inside async def. Use await directly.

TypeError: Object of type X is not JSON serializable

Cause: Returning a non-serializable object from a route.

# ❌ Returns datetime object directly
return {"created_at": user.created_at} # datetime not serializable

# ✅ Use Pydantic model — it handles serialization
return UserResponse.model_validate(user)

Or set json_encoders in model config:

model_config = ConfigDict(json_encoders={datetime: lambda v: v.isoformat()})

Common Pitfalls Summary

ErrorRoot CauseQuick Fix
422 on every POSTWrong Content-Type headerAdd -H "Content-Type: application/json"
404 for valid routeRouter not includedCall app.include_router(router)
500 with no detailUnhandled exceptionAdd global exception handler + logging
Model validation ignores extra fieldsDefault Pydantic v2 behaviorSet extra="forbid" to catch unexpected fields
DetachedInstanceErrorAccessing ORM object after session closeSet expire_on_commit=False

What's Next