How It Works Features Pricing Blog Error Guides
Log In Start Free Trial
FastAPI · Python

Fix ValidationError: pydantic.error_wrappers.ValidationError: 1 validation error for UserResponse - field required (type=value_error.missing) in FastAPI

This error occurs when the data returned by your endpoint does not match the response_model schema. FastAPI validates the response through Pydantic, and missing or mistyped fields trigger a ValidationError. Fix it by ensuring the returned data includes all required fields defined in the response model or by making optional fields truly Optional.

Reading the Stack Trace

Traceback (most recent call last): File "/app/venv/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py", line 406, in run_asgi result = await app(scope, receive, send) File "/app/venv/lib/python3.11/site-packages/starlette/routing.py", line 677, in __call__ await route.handle(scope, receive, send) File "/app/venv/lib/python3.11/site-packages/fastapi/routing.py", line 234, in app raw_response = await run_endpoint_function(dependant=dependant, values=values) File "/app/venv/lib/python3.11/site-packages/fastapi/routing.py", line 199, in serialize_response return field.validate(response_content, {}, loc=("response",)) File "/app/venv/lib/python3.11/site-packages/pydantic/fields.py", line 884, in validate raise ValidationError(errors, self.type_) pydantic.error_wrappers.ValidationError: 1 validation error for UserResponse email field required (type=value_error.missing)

Here's what each line means:

Common Causes

1. Database model missing a field the response model requires

The ORM model does not have a column that the Pydantic response model expects, so the serialized response is missing the field.

class UserResponse(BaseModel):
    id: int
    name: str
    email: str  # Required field

@app.get("/users/{user_id}", response_model=UserResponse)
def get_user(user_id: int, db: Session = Depends(get_db)):
    user = db.query(User).filter(User.id == user_id).first()
    return user  # User ORM model may not have 'email' populated

2. Returning a dict with missing keys

The endpoint returns a dictionary that is missing one or more required keys defined in the response model.

@app.get("/users/{user_id}", response_model=UserResponse)
def get_user(user_id: int):
    return {"id": user_id, "name": "Alice"}  # Missing 'email' key

3. Field name mismatch between ORM and Pydantic models

The ORM model uses a different column name than the Pydantic model expects, so the field is not mapped.

# ORM model has 'email_address' column
# Pydantic model expects 'email' field
class UserResponse(BaseModel):
    id: int
    name: str
    email: str  # Does not match ORM column 'email_address'

The Fix

Make the email field Optional with a default of None if it may not always be present. Add model_config with from_attributes=True (Pydantic v2) so the model can read attributes directly from ORM objects. Add a 404 check to handle missing users.

Before (broken)
from pydantic import BaseModel

class UserResponse(BaseModel):
    id: int
    name: str
    email: str

@app.get("/users/{user_id}", response_model=UserResponse)
def get_user(user_id: int, db: Session = Depends(get_db)):
    user = db.query(User).filter(User.id == user_id).first()
    return user
After (fixed)
from pydantic import BaseModel, ConfigDict
from typing import Optional

class UserResponse(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    id: int
    name: str
    email: Optional[str] = None

@app.get("/users/{user_id}", response_model=UserResponse)
def get_user(user_id: int, db: Session = Depends(get_db)):
    user = db.query(User).filter(User.id == user_id).first()
    if not user:
        raise HTTPException(status_code=404, detail="User not found")
    return user

Testing the Fix

import pytest
from fastapi.testclient import TestClient
from app.main import app

client = TestClient(app)


def test_get_user_with_all_fields():
    response = client.get("/users/1")
    if response.status_code == 200:
        data = response.json()
        assert "id" in data
        assert "name" in data
        assert "email" in data


def test_get_user_without_email():
    # User exists but has no email
    response = client.get("/users/2")
    if response.status_code == 200:
        data = response.json()
        assert data["email"] is None


def test_get_nonexistent_user_returns_404():
    response = client.get("/users/99999")
    assert response.status_code == 404


def test_response_excludes_sensitive_fields():
    response = client.get("/users/1")
    if response.status_code == 200:
        data = response.json()
        assert "password" not in data
        assert "hashed_password" not in data

Run your tests:

pytest tests/test_response_model.py -v

Pushing Through CI/CD

git checkout -b fix/fastapi-response-model,git add src/schemas/user.py src/routes/users.py tests/test_response_model.py,git commit -m "fix: make email optional in UserResponse and add from_attributes config",git push origin fix/fastapi-response-model

Your CI config should look something like this:

name: CI
on:
  pull_request:
    branches: [main]
jobs:
  test:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:15
        env:
          POSTGRES_DB: testdb
          POSTGRES_USER: postgres
          POSTGRES_PASSWORD: postgres
        ports:
          - 5432:5432
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.11'
          cache: 'pip'
      - run: pip install -r requirements.txt
      - run: pytest --tb=short -q
        env:
          DATABASE_URL: postgresql://postgres:postgres@localhost:5432/testdb

The Full Manual Process: 18 Steps

Here's every step you just went through to fix this one bug:

  1. Notice the error alert or see it in your monitoring tool
  2. Open the error dashboard and read the stack trace
  3. Identify the file and line number from the stack trace
  4. Open your IDE and navigate to the file
  5. Read the surrounding code to understand context
  6. Reproduce the error locally
  7. Identify the root cause
  8. Write the fix
  9. Run the test suite locally
  10. Fix any failing tests
  11. Write new tests covering the edge case
  12. Run the full test suite again
  13. Create a new git branch
  14. Commit and push your changes
  15. Open a pull request
  16. Wait for code review
  17. Merge and deploy to production
  18. Monitor production to confirm the error is resolved

Total time: 30-60 minutes. For one bug.

Or Let bugstack Fix It in Under 2 minutes

Every step above? bugstack does it automatically.

Step 1: Install the SDK

pip install bugstack

Step 2: Initialize

import bugstack

bugstack.init(api_key=os.environ["BUGSTACK_API_KEY"])

Step 3: There is no step 3.

bugstack handles everything from here:

  1. Captures the stack trace and request context
  2. Pulls the relevant source files from your GitHub repo
  3. Analyzes the error and understands the code context
  4. Generates a minimal, verified fix
  5. Runs your existing test suite
  6. Pushes through your CI/CD pipeline
  7. Deploys to production (or opens a PR for review)

Time from error to fix deployed: Under 2 minutes.

Human involvement: zero.

Try bugstack Free →

No credit card. 5-minute setup. Cancel anytime.

Deploying the Fix (Manual Path)

  1. Run the test suite locally to confirm response serialization works for all user states.
  2. Open a pull request with the schema and endpoint fixes.
  3. Wait for CI checks to pass on the PR.
  4. Have a teammate review and approve the PR.
  5. Merge to main and verify API responses match the expected schema in staging.

Frequently Asked Questions

BugStack validates that every endpoint's returned data passes the response_model validation, tests edge cases like missing optional fields, and confirms no sensitive fields leak through the schema.

BugStack never pushes directly to production. Every fix goes through a pull request with full CI checks, so your team can review the schema changes before merging.

response_model actively filters and validates the response data through Pydantic, stripping extra fields. Return type hints are only for documentation and IDE support, they do not perform runtime validation.

In Pydantic v2, use model_config = ConfigDict(from_attributes=True). In Pydantic v1, use class Config: orm_mode = True. Both allow Pydantic to read data from ORM model attributes.