Skip to content

Conversation

@maxisbey
Copy link
Contributor

This PR fixes a compatibility issue with pydantic 2.12+ where fields using Annotated[T, Field(default)] without explicit parameter defaults were incorrectly marked as required in JSON schemas.

Motivation and Context

Pydantic 2.12.0 introduced a breaking change in how FieldInfo.from_annotated_attribute() handles defaults. When passing PydanticUndefined as the second parameter, it now overwrites any default value specified inside Field() within an Annotated type. This causes fields that should be optional (with defaults from Field()) to be incorrectly marked as required in the generated JSON schema.

The issue affects function parameters like:

def my_function(
    param: Annotated[int, Field(1, description="Has default")]
):
    ...

With pydantic 2.12+, this parameter would be marked as required in the JSON schema, even though Field(1) specifies a default value.

How Has This Been Tested?

  • Existing test test_complex_function_json_schema validates the fix (tests fields with Field(default) in Annotated types)
  • All 31 tests in test_func_metadata.py pass
  • The fix maintains backward compatibility with pydantic 2.11.x

The solution detects when an Annotated type contains a FieldInfo with a default and uses FieldInfo.from_annotation() to preserve that default, while continuing to use from_annotated_attribute() for standard cases where parameter defaults should take precedence.

Breaking Changes

None. This is a bug fix that maintains backward compatibility with pydantic 2.11 while adding forward compatibility with pydantic 2.12+.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

This fix prepares the codebase for pydantic 2.12+, which will be included in dependency updates. The change is minimal and focused on preserving the intended behavior: defaults specified in Field() within Annotated types should be respected in the JSON schema.

The implementation checks for the presence of a FieldInfo with a non-undefined default in the Annotated metadata and chooses the appropriate FieldInfo construction method accordingly.

When using Annotated[T, Field(default)] without an explicit parameter
default (= value), pydantic 2.12+ changed FieldInfo.from_annotated_attribute()
to overwrite the Field's default with PydanticUndefined, incorrectly marking
fields as required in the JSON schema.

This fix checks if a Field with a default exists in the Annotated metadata
and uses FieldInfo.from_annotation() to preserve that default, while still
using from_annotated_attribute() for the standard case where parameter
defaults take precedence.

The fix maintains backward compatibility with pydantic 2.11 and earlier
while ensuring correct behavior with 2.12+.
@maxisbey maxisbey added bug Something isn't working P3 Nice to haves, rare edge cases labels Nov 10, 2025
@maxisbey maxisbey requested a review from Kludex November 12, 2025 16:38
@Viicos
Copy link
Contributor

Viicos commented Nov 13, 2025

@maxisbey I'm on mobile but I think #1496 actually fixes it, by avoiding relying on the FieldInfo methods that are not meant to be used externally/are not behaving as users would expect.

@maxisbey
Copy link
Contributor Author

@maxisbey I'm on mobile but I think #1496 actually fixes it, by avoiding relying on the FieldInfo methods that are not meant to be used externally/are not behaving as users would expect.

Oh perfect, I'd be keen to get that in then! Do you have time to fix the merge conflicts?

@maxisbey maxisbey closed this Nov 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working P3 Nice to haves, rare edge cases

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants