obsidian/wiki/concepts/pydantic-mongodb-patch-missing-fields.md
2026-05-10 21:21:13 +01:00

3.2 KiB

title aliases tags sources created updated
Manual MongoDB Patch Missing Pydantic Required Fields → 500 on GET
mongodb-manual-patch
pydantic-required-fields-patch
mongo-patch-500
mongodb
pydantic
fastapi
debugging
silent-failure
daily/2026-05-08.md
2026-05-08 2026-05-08

Manual MongoDB Patch Missing Pydantic Required Fields → 500 on GET

When patching a MongoDB document directly (via MongoDB shell, Atlas UI, or a one-off script) without including all fields required by the FastAPI Pydantic response model, the GET endpoint that reads that document returns HTTP 500 with no readable traceback in standard application logs.

The Failure Mode

# Pydantic response model (simplified)
class JobResponse(BaseModel):
    id: str
    status: str
    occurred_at: datetime   # required — no default
    error_message: Optional[str] = None

# GET /jobs/{id} uses response_model=JobResponse
# If the document in MongoDB is missing 'occurred_at', FastAPI
# will raise ValidationError during serialization → 500, no trace in app logs

Manual patch that triggers the bug:

// MongoDB shell — missing 'occurred_at'
db.jobs.updateOne(
  { _id: ObjectId("...") },
  { $set: { status: "failed", error_message: "network timeout" } }
)
// 'occurred_at' not included → document now fails GET deserialization

Why No Traceback

FastAPI serializes the response model after the route handler returns. The ValidationError happens in the response rendering layer. Without explicit exception logging on the response serializer, the only visible signal is the 500 status code.

Fix: Always Include Required Fields in Manual Patches

// MongoDB shell — include ALL Pydantic-required fields
db.jobs.updateOne(
  { _id: ObjectId("...") },
  {
    $set: {
      status: "failed",
      error_message: "network timeout",
      occurred_at: new Date()   // ← required field included
    }
  }
)

Diagnosis Checklist

When GET /entity/{id} returns 500 after a manual database operation:

  1. Check the Pydantic response model for required fields (no = None / = Field(default=...))
  2. Compare the actual MongoDB document against the model using:
    from bson import ObjectId
    doc = db.collection.find_one({"_id": ObjectId("...")})
    print(doc.keys())  # compare against Pydantic model fields
    
  3. Add any missing required fields to the document
  4. Re-test the GET endpoint

Prevention

When writing admin/debug scripts that patch MongoDB documents:

# Use the Pydantic model as a schema reference
required_fields = [
    name for name, field in JobResponse.model_fields.items()
    if field.is_required()
]
# Verify your patch dict includes all required_fields

Sources

  • daily/2026-05-08.md — Discovered during video-accessibility pipeline debugging; GET /jobs/{id} returned 500 after a manual MongoDB patch that set status: "failed" without including the required occurred_at field from the JobFailure Pydantic model