{"record":{"id":"9aff1be46db92366","repo":"BerriAI/litellm","slug":"cannot-create-domain-model-from-none-record","errorCode":null,"errorMessage":"Cannot create domain model from None record","messagePattern":"Cannot create domain model from None record","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/models/base.py","lineNumber":27,"sourceCode":"\n\nclass DomainModel(BaseModel):\n    \"\"\"Base class for all domain models.\"\"\"\n\n    model_config = ConfigDict(\n        from_attributes=True,\n        protected_namespaces=(),\n        extra=\"ignore\",\n    )\n\n    created_at: datetime | None = None\n    updated_at: datetime | None = None\n\n    @classmethod\n    def from_db_record(cls, record: Any) -> \"DomainModel\":\n        \"\"\"Create a domain model from a database record.\"\"\"\n        if record is None:\n            raise ValueError(\"Cannot create domain model from None record\")\n        if isinstance(record, dict):\n            return cls(**record)\n        if hasattr(record, \"model_dump\") and callable(record.model_dump):\n            return cls(**record.model_dump())\n        if hasattr(record, \"dict\") and callable(record.dict):\n            return cls(**record.dict())\n        return cls(**dict(record))\n\n    def to_db_dict(self, exclude_unset: bool = False) -> dict[str, Any]:\n        \"\"\"Convert domain model to a dictionary for database operations.\"\"\"\n        return self.model_dump(exclude_none=True, exclude_unset=exclude_unset)\n","sourceCodeStart":9,"sourceCodeEnd":39,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/models/base.py#L9-L39","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"# before\nuser = User.from_db_record(users_table.get_user(user_id))\n\n# after\nrecord = users_table.get_user(user_id)\nif record is None:\n    raise LookupError(f\"user {user_id} not found\")\nuser = User.from_db_record(record)","handlingStrategy":"type-guard","validationCode":"record = repo.get_user(user_id)\nif record is None:\n    raise LookupError(f\"user {user_id} not found\")\nuser = User.from_db_record(record)","typeGuard":"def is_record(record: object) -> bool:\n    return record is not None and (isinstance(record, dict) or hasattr(record, \"model_dump\") or hasattr(record, \"dict\") or hasattr(record, \"__iter__\"))","tryCatchPattern":"try:\n    user = User.from_db_record(record)\nexcept ValueError as e:\n    if \"None record\" in str(e):\n        raise LookupError(\"requested row does not exist\") from e\n    raise","preventionTips":["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"],"tags":["database","domain-model","none-record","pydantic"],"backgroundTag":"null-database-record","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}