fix: upgrade datamodel-code-generator to fix RootModel serialization bug#745
Merged
fix: upgrade datamodel-code-generator to fix RootModel serialization bug#745
Conversation
Upgrades datamodel-code-generator from >=0.25.8 to >=0.47.0 to fix a bug
where RootModel fields with default values were generated with raw primitive
defaults instead of proper RootModel instances.
This caused "'str' object has no attribute 'root'" errors during FastAPI
response serialization for fields like:
- service_tier: ServiceTier (3 occurrences)
- reasoning_effort: ReasoningEffort (5 occurrences)
- search_context_size: WebSearchContextSize (1 occurrence)
The fix (datamodel-code-generator PR #2714) generates proper default_factory:
```python
# Before (broken):
service_tier: Annotated[Optional[ServiceTier], Field()] = "auto"
# After (fixed):
service_tier: Annotated[ServiceTier | None, Field(default_factory=lambda: ServiceTier('auto'))]
```
Fixes serialization error introduced in commit 0cbb58d.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The new version of datamodel-code-generator now imports constr for constrained string types. Add this export to the custom pydantic_types module. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The newer datamodel-codegen changed CreateChatCompletionRequest.model from str to ModelIdsShared (a RootModel). The override is still compatible at runtime since ModelIdsShared wraps str. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The type field was optional without a default, which caused datamodel-codegen to generate `Literal["message"] | None = None`. This broke Pydantic's discriminated union since discriminator fields need concrete Literal types. Adding `default: message` to the spec generates proper code with a non-None default value. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The OpenAPI spec has InputMessage and OutputMessage both with type='message', which causes Pydantic's discriminated union to fail with "Value 'message' mapped to multiple choices". Removing the discriminator makes Pydantic try each model in the union until one validates. Also reverted the InputMessage.type default change since it wasn't needed. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Handle all variations of the discriminator pattern in sed. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…ponseMessage The OpenAPI spec marked these as required but the actual API doesn't always return them (refusal is only present when model refuses). This caused validation errors when deserializing responses. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace blanket sed-based discriminator removal with a targeted Python post-processing script that only removes discriminator='type' from unions with conflicting type values: - Item: InputMessage + OutputMessage (both type='message') - InputItem: EasyInputMessage + InputMessage + OutputMessage (all type='message') Other unions (ToolModel, AnnotationModel, ItemResource, RealtimeClientEvent, RealtimeServerEvent, ResponseStreamEvent, etc.) retain their discriminators for better Pydantic validation performance. Also fix .black.toml to use force-exclude instead of exclude, which is required when files are passed explicitly (as pre-commit does). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The model field is overridden from ModelIdsShared to str to support a broader set of model IDs than the OpenAI enum. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
datamodel-code-generatorfrom>=0.25.8to>=0.47.0to fix a serialization bugProblem
After commit 0cbb58d ("Update openai api schema #742"), the API started throwing errors:
This happened during FastAPI response serialization for endpoints using the OpenAI-compatible API.
Root Cause
The
datamodel-code-generatorhad a bug (Issue #2027) where RootModel fields with default values were generated with raw primitive defaults:When Pydantic tries to serialize this, it expects a
ServiceTierRootModel instance with a.rootattribute, but gets a plain string.Fix
The fix was merged in
datamodel-code-generatorPR #2714 and released in v0.47.0. It generates properdefault_factory:Affected Fields
service_tier: ServiceTier(3 occurrences)reasoning_effort: ReasoningEffort(5 occurrences)search_context_size: WebSearchContextSize(1 occurrence)Test plan
🤖 Generated with Claude Code