Skip to content

🐛 Fix unhashable Annotated type in get_definitions OpenAPI schema generation#15429

Open
Yuerchu wants to merge 4 commits intofastapi:masterfrom
Yuerchu:fix/unhashable-annotated-in-get-definitions
Open

🐛 Fix unhashable Annotated type in get_definitions OpenAPI schema generation#15429
Yuerchu wants to merge 4 commits intofastapi:masterfrom
Yuerchu:fix/unhashable-annotated-in-get-definitions

Conversation

@Yuerchu
Copy link
Copy Markdown

@Yuerchu Yuerchu commented Apr 25, 2026

Summary

  • get_definitions() in fastapi/_compat/v2.py uses a set comprehension to collect field annotations for deduplication
  • On Python 3.14 with Pydantic v2.13+, some Annotated types contain FieldInfoMetadata objects that are not hashable, causing a TypeError when generating the OpenAPI schema:
TypeError: cannot use 'typing._AnnotatedAlias' as a set element (unhashable type: 'FieldInfoMetadata')
  • This is triggered when routes use Annotated parameters with metadata such as Query(max_length=..., description=...) or similar constructs that produce unhashable Pydantic field metadata

Fix

Use id() for identity-based deduplication instead of relying on __hash__ of annotation objects. Since annotations are interned type objects, id() comparison is semantically equivalent for this filtering purpose.

Changes

-    input_types = {f.field_info.annotation for f in fields}
+    input_type_ids = {id(f.field_info.annotation) for f in fields}
     unique_flat_model_fields = {
-        f for f in flat_model_fields if f.field_info.annotation not in input_types
+        f for f in flat_model_fields if id(f.field_info.annotation) not in input_type_ids
     }

Environment

  • Python 3.14.3
  • Pydantic 2.13.3
  • FastAPI 0.136.1

Yuerchu and others added 2 commits April 26, 2026 01:53
… generation

`get_definitions()` uses a set comprehension to collect field annotations
for deduplication. However, on Python 3.14 with Pydantic v2.13+, some
`Annotated` types contain `FieldInfoMetadata` objects that are not
hashable, causing a `TypeError`:

    TypeError: cannot use 'typing._AnnotatedAlias' as a set element
    (unhashable type: 'FieldInfoMetadata')

This is triggered when routes use `Annotated` parameters with metadata
such as `Query(max_length=..., description=...)` or similar constructs
that produce unhashable Pydantic field metadata.

Fix: use `id()` for identity-based deduplication instead of relying on
`__hash__` of annotation objects. Since annotations are interned type
objects, `id()` comparison is semantically equivalent for this filtering
purpose.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Apr 25, 2026

Merging this PR will not alter performance

✅ 20 untouched benchmarks


Comparing Yuerchu:fix/unhashable-annotated-in-get-definitions (36ce51f) with master (f43cc1c)1

Open in CodSpeed

Footnotes

  1. No successful run was found on master (b445855) during the generation of this report, so f43cc1c was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

Yuerchu and others added 2 commits April 26, 2026 12:41
Add test that directly exercises get_definitions() with an Annotated
type containing unhashable metadata (simulating SQLModel extension
field-info objects). The test fails on main and passes with the fix.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comment on lines +8 to +9
"""Simulates third-party field metadata (e.g. from SQLModel extensions)
that does not implement ``__hash__``."""
Copy link
Copy Markdown
Member

@YuriiMotov YuriiMotov Apr 26, 2026

Choose a reason for hiding this comment

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

SQLModel is already in test dependencies, so you can use it to make this test more realistic.
Ideally, it should be a FastAPI app, not just get_definitions

@YuriiMotov
Copy link
Copy Markdown
Member

YuriiMotov commented Apr 26, 2026

Please, review changes carefully before opening PR.
AI-generated PRs without proper human review will be closed. See https://fastapi.tiangolo.com/contributing/#automated-code-and-ai

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants