Skip to content

KeyError when inhering from a self-referencing generic model #9969

@rizar

Description

@rizar

Initial Checks

  • I confirm that I'm using Pydantic V2

Description

I have this very short code snippet below that crashes with KeyError, see stack trace. Should be self-explanatory. Looks like a bug.

python .local/my_issue2.py
/home/toolkit/.conda/envs/tapes/lib/python3.11/site-packages/pydantic/_migration.py:283: UserWarning: `pydantic.generics:GenericModel` has been moved to `pydantic.BaseModel`.
  warnings.warn(f'`{import_path}` has been moved to `{new_location}`.')
Traceback (most recent call last):
  File "/home/toolkit/dist/research-pyllmd/.local/my_issue2.py", line 11, in <module>
    class M2(M1[str]):
  File "/home/toolkit/.conda/envs/tapes/lib/python3.11/site-packages/pydantic/_internal/_model_construction.py", line 205, in __new__
    complete_model_class(
  File "/home/toolkit/.conda/envs/tapes/lib/python3.11/site-packages/pydantic/_internal/_model_construction.py", line 544, in complete_model_class
    schema = gen_schema.clean_schema(schema)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/toolkit/.conda/envs/tapes/lib/python3.11/site-packages/pydantic/_internal/_generate_schema.py", line 448, in clean_schema
    schema = simplify_schema_references(schema)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/toolkit/.conda/envs/tapes/lib/python3.11/site-packages/pydantic/_internal/_core_utils.py", line 463, in simplify_schema_references
    schema = walk_core_schema(schema, count_refs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/toolkit/.conda/envs/tapes/lib/python3.11/site-packages/pydantic/_internal/_core_utils.py", line 414, in walk_core_schema
    return f(schema.copy(), _dispatch)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/toolkit/.conda/envs/tapes/lib/python3.11/site-packages/pydantic/_internal/_core_utils.py", line 459, in count_refs
    recurse(definitions[ref], count_refs)
  File "/home/toolkit/.conda/envs/tapes/lib/python3.11/site-packages/pydantic/_internal/_core_utils.py", line 197, in walk
    return f(schema, self._walk)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/home/toolkit/.conda/envs/tapes/lib/python3.11/site-packages/pydantic/_internal/_core_utils.py", line 447, in count_refs
    return recurse(s, count_refs)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/home/toolkit/.conda/envs/tapes/lib/python3.11/site-packages/pydantic/_internal/_core_utils.py", line 200, in _walk
    schema = self._schema_type_to_method[schema['type']](schema.copy(), f)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/toolkit/.conda/envs/tapes/lib/python3.11/site-packages/pydantic/_internal/_core_utils.py", line 209, in _handle_other_schemas
    schema['schema'] = self.walk(sub_schema, f)  # type: ignore
                       ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/toolkit/.conda/envs/tapes/lib/python3.11/site-packages/pydantic/_internal/_core_utils.py", line 197, in walk
    return f(schema, self._walk)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/home/toolkit/.conda/envs/tapes/lib/python3.11/site-packages/pydantic/_internal/_core_utils.py", line 447, in count_refs
    return recurse(s, count_refs)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/home/toolkit/.conda/envs/tapes/lib/python3.11/site-packages/pydantic/_internal/_core_utils.py", line 200, in _walk
    schema = self._schema_type_to_method[schema['type']](schema.copy(), f)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/toolkit/.conda/envs/tapes/lib/python3.11/site-packages/pydantic/_internal/_core_utils.py", line 337, in handle_model_fields_schema
    replaced_field['schema'] = self.walk(v['schema'], f)
                               ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/toolkit/.conda/envs/tapes/lib/python3.11/site-packages/pydantic/_internal/_core_utils.py", line 197, in walk
    return f(schema, self._walk)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/home/toolkit/.conda/envs/tapes/lib/python3.11/site-packages/pydantic/_internal/_core_utils.py", line 447, in count_refs
    return recurse(s, count_refs)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/home/toolkit/.conda/envs/tapes/lib/python3.11/site-packages/pydantic/_internal/_core_utils.py", line 200, in _walk
    schema = self._schema_type_to_method[schema['type']](schema.copy(), f)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/toolkit/.conda/envs/tapes/lib/python3.11/site-packages/pydantic/_internal/_core_utils.py", line 209, in _handle_other_schemas
    schema['schema'] = self.walk(sub_schema, f)  # type: ignore
                       ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/toolkit/.conda/envs/tapes/lib/python3.11/site-packages/pydantic/_internal/_core_utils.py", line 197, in walk
    return f(schema, self._walk)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/home/toolkit/.conda/envs/tapes/lib/python3.11/site-packages/pydantic/_internal/_core_utils.py", line 459, in count_refs
    recurse(definitions[ref], count_refs)
            ~~~~~~~~~~~^^^^^
KeyError: '__main__.M1:27570992[str:8801856]'

Example Code

from typing import Generic, TypeVar

from pydantic import BaseModel

X = TypeVar("X")

class M1(BaseModel, Generic[X]):
    bar: 'M1[X]'
    
class M2(M1[str]):
    pass

Python, Pydantic & OS Version

pydantic version: 2.8.2
        pydantic-core version: 2.20.1
          pydantic-core build: profile=release pgo=true
                 install path: /home/toolkit/.conda/envs/tapes/lib/python3.11/site-packages/pydantic
               python version: 3.11.9 (main, Apr 19 2024, 16:48:06) [GCC 11.2.0]
                     platform: Linux-5.15.0-1040-nvidia-x86_64-with-glibc2.35
             related packages: typing_extensions-4.12.2 fastapi-0.111.0
                       commit: unknown

Metadata

Metadata

Assignees

Labels

bug V2Bug related to Pydantic V2topic-genericsRelated to generics

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions