BerriAI/litellm · error · ValueError
Cannot create domain model from None record
Error message
Cannot create domain model from None record
What it means
DomainModel.from_db_record() converts a database row (dict, pydantic model with model_dump()/dict(), or any row object) into the domain model. Passing None — typically a 'not found' query result — raises ValueError immediately instead of producing a half-built object.
Source
Thrown at litellm/models/base.py:27
class DomainModel(BaseModel):
"""Base class for all domain models."""
model_config = ConfigDict(
from_attributes=True,
protected_namespaces=(),
extra="ignore",
)
created_at: datetime | None = None
updated_at: datetime | None = None
@classmethod
def from_db_record(cls, record: Any) -> "DomainModel":
"""Create a domain model from a database record."""
if record is None:
raise ValueError("Cannot create domain model from None record")
if isinstance(record, dict):
return cls(**record)
if hasattr(record, "model_dump") and callable(record.model_dump):
return cls(**record.model_dump())
if hasattr(record, "dict") and callable(record.dict):
return cls(**record.dict())
return cls(**dict(record))
def to_db_dict(self, exclude_unset: bool = False) -> dict[str, Any]:
"""Convert domain model to a dictionary for database operations."""
return self.model_dump(exclude_none=True, exclude_unset=exclude_unset)
View on GitHub (pinned to 77b7c6c40c)
Solutions
- Check for None first and translate it into a domain-level not-found error
- Use a repository method that raises a typed DoesNotExist exception when the query misses
- If the row should exist, fix the query (id/tenant filter) rather than the mapper
Example fix
# before
user = User.from_db_record(users_table.get_user(user_id))
# after
record = users_table.get_user(user_id)
if record is None:
raise LookupError(f"user {user_id} not found")
user = User.from_db_record(record) Defensive patterns
Strategy: type-guard
Validate before calling
record = repo.get_user(user_id)
if record is None:
raise LookupError(f"user {user_id} not found")
user = User.from_db_record(record) Type guard
def is_record(record: object) -> bool:
return record is not None and (isinstance(record, dict) or hasattr(record, "model_dump") or hasattr(record, "dict") or hasattr(record, "__iter__")) Try / catch
try:
user = User.from_db_record(record)
except ValueError as e:
if "None record" in str(e):
raise LookupError("requested row does not exist") from e
raise Prevention
- Treat a None query result as a not-found domain event at the repository layer
- Never pass query results straight into mappers without a None check
- Cover the not-found path in tests for every repository getter
When it happens
Trigger: A repository getter returns None (no matching row) and the caller immediately does User.from_db_record(record); read-after-delete flows; queries with overly tight filters (wrong tenant/id).
Common situations: Service layer with no not-found handling; race where the row is deleted between check and read; tests with empty fixtures; soft-deleted rows excluded by the query.
Related errors
- DB not connected. This endpoint needs a database; set DATABA
- DB not connected. This endpoint needs a database; set DATABA
- Database not connected
- Database not connected. Connect a database to your proxy - h
- Error retrieving usage data: {e}
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/9aff1be46db92366.
Report an issue: GitHub.