Skip to content

Conversation

@kafkas
Copy link
Member

@kafkas kafkas commented Dec 20, 2025

Description

Linear ticket: FER-8077

A previous fix, #11011 only helped when callers invoked model_validate() directly, but it did not apply to nested validation paths (e.g. when a parent model is validated via TypeAdapter), so wire keys like is_base64_encoded could still fail with “Field required” inside nested objects. This PR fixes nested decoding by emitting pydantic.Field(alias=...) for aliased fields so Pydantic v2 can resolve wire aliases during compiled nested validation.

Changes Made

  • Ensures pydantic.Field(alias=...) is emitted for aliased fields
  • Removes the UncheckedBaseModel.model_validate Pydantic v2 override
  • Adds a test for validation via TypeAdapter

Testing

  • Unit tests added/updated
  • Manual testing completed

Note

Emit pydantic.Field(alias=...) for aliased fields and update parsing/config so aliases are honored during nested Pydantic v2 validation; remove the v2 model_validate override.

  • Codegen / Models:
    • Emit pydantic.Field(alias=...) for aliased fields across generated models (including optional fields, unions, nested objects, and examples).
    • Update initializer to always pass alias to field definitions.
  • Core utilities:
    • Refine parse_obj_as to detect real Pydantic aliases and only pre-dealias when needed; supports both v1 and v2 paths.
    • Remove UncheckedBaseModel.model_validate override for Pydantic v2.
    • Enable population by field name and alias (populate_by_name / allow_population_by_field_name) in UniversalBaseModel.
  • Tests/Seeds:
    • Regenerate seed SDKs and test utilities to use pydantic.Field(alias=...) and new model config to ensure nested validation works with wire aliases.

Written by Cursor Bugbot for commit 5d2873c. This will update automatically on new commits. Configure here.

@github-actions
Copy link
Contributor

github-actions bot commented Dec 20, 2025

🌱 Seed Test Selector

Select languages to run seed tests for:

  • Python
  • TypeScript
  • Java
  • Go
  • Ruby
  • C#
  • PHP
  • Swift
  • Rust
  • OpenAPI
  • Postman

How to use: Click the ⋯ menu above → "Edit" → check the boxes you want → click "Update comment". Tests will run automatically and snapshots will be committed to this PR.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the final PR Bugbot will review for you during this billing cycle

Your free Bugbot reviews will reset on January 18

Details

You are on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

@kafkas kafkas force-pushed the anar/fer-8077-elevenlabs-pydantic-v2-decoding-error-for-nested-field branch from 13c594b to ed09d46 Compare December 22, 2025 10:08
# the model encodes aliasing:
# - If the model uses real Pydantic aliases (Field(alias=...)), pass wire keys through unchanged.
# - If the model encodes aliasing only via FieldMetadata, pre-dealias before validation.
if inspect.isclass(type_) and issubclass(type_, pydantic.BaseModel):
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrong base class in issubclass check for v1-on-v2 context

The alias detection logic checks issubclass(type_, pydantic.BaseModel) but UniversalBaseModel in this file extends pydantic.v1.BaseModel (line 56). In Pydantic v2, these are entirely separate class hierarchies - pydantic.v1.BaseModel is NOT a subclass of pydantic.BaseModel. This means the condition will always be False for any model in the with_pydantic_v1_on_v2 context, causing the alias detection code to never execute. The check needs to use pydantic.v1.BaseModel instead to match the base class actually used by models in this context.

Fix in Cursor Fix in Web

else convert_and_respect_annotation_metadata(object_=object_, annotation=type_, direction="read")
)
else:
dealiased_object = convert_and_respect_annotation_metadata(object_=object_, annotation=type_, direction="read")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing allow_population_by_field_name config in v1-on-v2 variant

The UniversalBaseModel.Config class in the with_pydantic_v1_on_v2 variant is missing allow_population_by_field_name = True, which this PR adds to all other variants (both generated seed files and the similar with_pydantic_v1_on_v2/with_aliases variant). This config option is needed to allow Pydantic v1 to accept both wire aliases and Python field names. Combined with the wrong issubclass check bug, when de-aliasing always occurs but models also have pydantic.Field(alias=...) set, validation will fail because Pydantic v1 without this config only accepts the alias.

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants