Jump to solution
Verify

The Fix

pip install pydantic==2.11.5

Based on closed pydantic/pydantic issue #11849 · PR/commit linked

Production note: This tends to surface only under concurrency. Reproduce with load tests and watch for lock contention/cancellation paths.

Jump to Verify Open PR/Commit
@@ -620,9 +620,11 @@ def model_rebuild( for attr in ('__pydantic_core_schema__', '__pydantic_validator__', '__pydantic_serializer__'): - if attr in cls.__dict__: + if attr in cls.__dict__ and not isinstance(getattr(cls, attr), _mock_val_ser.MockValSer): # Deleting the validator/serializer is necessary as otherwise they can get reused in
repro.py
from __future__ import annotations # support forward refs from pydantic import BaseModel , model_validator, ValidationInfo from typing import Self class Direct(BaseModel): model_config = ConfigDict(populate_by_name=True) id: str description: Optional[Translatable] = None ... class Translatable(BaseModel): en: str = "" ... d = Direct(id="test", description=Translatable(en="ok")) # raises PydanticUserError("Pydantic models should inherit from BaseModel, BaseModel cannot be instantiated directly") # The translatable was intantiated correctly, but `Direct` seems do BE BaseModel # second example class A(BaseModel): @model_validator(mode="after") def _modelAfterValidator(self, info: ValidationInfo) -> Self: ... return self class B(A): id: str class C(B): name: str | None = None forward: Foo | None = None class Foo: pass c1 = C.model_validate({"name": "test", "id": "ok1"}) # correctly instantiates c2 = C.model_validate({"name": "test", "id": "ok2"}) # correctly instantiates c3 = C.model_validate({"name": "test", "id": "ok3"}) # correctly instantiates print(c1) # B(id="ok1") __repr__ shows class B instead of C!!! print(c2) # B(id="ok2") c1.name # raises AttributeError("'B' object has no attribute 'name'"). again B instead of C
verify
Re-run the minimal reproduction on your broken version, then apply the fix and re-run.
fix.md
Option A — Upgrade to fixed release\npip install pydantic==2.11.5\nWhen NOT to use: This fix should not be applied if the application does not use multi-threading or multi-processing.\n\nOption C — Workaround\nfor now, but not a safe permanent fix, or something easily done at scale in large repos.\nWhen NOT to use: This fix should not be applied if the application does not use multi-threading or multi-processing.\n\n

Why This Fix Works in Production

  • Trigger: (race condition?) Subclass skipped in model instantiation
  • Mechanism: A race condition in model instantiation caused models to be skipped during initialization
  • Why the fix works: Addresses a race condition in model instantiation by ensuring that mock validators/serializers are not deleted prematurely during model rebuilds. (first fixed release: 2.11.5).
Production impact:
  • If left unfixed, failures can be intermittent under concurrency (hard to reproduce; shows up as sporadic 5xx/timeouts).

Why This Breaks in Prod

  • Shows up under Python 3.13 in real deployments (not just unit tests).
  • A race condition in model instantiation caused models to be skipped during initialization
  • Production symptom (often without a traceback): (race condition?) Subclass skipped in model instantiation

Proof / Evidence

Discussion

High-signal excerpts from the issue thread (symptoms, repros, edge-cases).

“Hi. Managed to semi-reliably reproduce when using threads, see https://github.com/raulparada/pydantic-repro-11849. I'll try making it clearer / getting the parameters right (I'm getting the error just…”
@raulparada · 2025-05-07 · repro detail · source
“Couldn't manage to make it fail more reliably but maybe a kind soul with more understanding of threading (/pydantic) can help hit the sweet spot,…”
@raulparada · 2025-05-08 · repro detail · source
“I'm >150 iterations on https://github.com/pydantic/pydantic/commit/f43102e8a3ac1d7ce0e341a3bdb495478780ba02 without seeing the issue, so promising @Viicos! 🎉 update: >600 and still no issue, seems fixed”
@raulparada · 2025-05-08 · source
“While anecdotal I can confirm we have been hitting very similar issues”
@DanielNoord · 2025-05-07 · source

Failure Signature (Search String)

  • (race condition?) Subclass skipped in model instantiation
  • [to be clear, the examples are not able to reproduce the race condition as-is, but they illustrate the relevant models involved]
Copy-friendly signature
signature.txt
Failure Signature ----------------- (race condition?) Subclass skipped in model instantiation [to be clear, the examples are not able to reproduce the race condition as-is, but they illustrate the relevant models involved]

Error Message

Signature-only (no traceback captured)
error.txt
Error Message ------------- (race condition?) Subclass skipped in model instantiation [to be clear, the examples are not able to reproduce the race condition as-is, but they illustrate the relevant models involved]

Minimal Reproduction

repro.py
from __future__ import annotations # support forward refs from pydantic import BaseModel , model_validator, ValidationInfo from typing import Self class Direct(BaseModel): model_config = ConfigDict(populate_by_name=True) id: str description: Optional[Translatable] = None ... class Translatable(BaseModel): en: str = "" ... d = Direct(id="test", description=Translatable(en="ok")) # raises PydanticUserError("Pydantic models should inherit from BaseModel, BaseModel cannot be instantiated directly") # The translatable was intantiated correctly, but `Direct` seems do BE BaseModel # second example class A(BaseModel): @model_validator(mode="after") def _modelAfterValidator(self, info: ValidationInfo) -> Self: ... return self class B(A): id: str class C(B): name: str | None = None forward: Foo | None = None class Foo: pass c1 = C.model_validate({"name": "test", "id": "ok1"}) # correctly instantiates c2 = C.model_validate({"name": "test", "id": "ok2"}) # correctly instantiates c3 = C.model_validate({"name": "test", "id": "ok3"}) # correctly instantiates print(c1) # B(id="ok1") __repr__ shows class B instead of C!!! print(c2) # B(id="ok2") c1.name # raises AttributeError("'B' object has no attribute 'name'"). again B instead of C

Environment

  • Python: 3.13
  • Pydantic: 2

What Broke

Models occasionally fail to initialize correctly, leading to runtime errors in production.

Why It Broke

A race condition in model instantiation caused models to be skipped during initialization

Fix Options (Details)

Option A — Upgrade to fixed release Safe default (recommended)

pip install pydantic==2.11.5

When NOT to use: This fix should not be applied if the application does not use multi-threading or multi-processing.

Use when you can deploy the upstream fix. It is usually lower-risk than long-lived workarounds.

Option C — Workaround Temporary workaround

for now, but not a safe permanent fix, or something easily done at scale in large repos.

When NOT to use: This fix should not be applied if the application does not use multi-threading or multi-processing.

Use only if you cannot change versions today. Treat this as a stopgap and remove once upgraded.

Fix reference: https://github.com/pydantic/pydantic/pull/11890

First fixed release: 2.11.5

Last verified: 2026-02-09. Validate in your environment.

Get updates

We publish verified fixes weekly. No spam.

Subscribe

When NOT to Use This Fix

  • This fix should not be applied if the application does not use multi-threading or multi-processing.

Verify Fix

verify
Re-run the minimal reproduction on your broken version, then apply the fix and re-run.

Did This Fix Work in Your Case?

Quick signal helps us prioritize which fixes to verify and improve.

Prevention

  • Add a CI check that diffs key outputs after upgrades (OpenAPI schema snapshots, JSON payload shapes, CLI output).
  • Upgrade behind a canary and run integration tests against the canary before 100% rollout.
  • Add a TLS smoke test that performs a real handshake in CI (include CA bundle validation and hostname checks).
  • Alert on handshake failures by error string and endpoint to catch cert/CA changes quickly.

Version Compatibility Table

VersionStatus
2.11.5 Fixed

Related Issues

No related fixes found.

Sources

We don’t republish the full GitHub discussion text. Use the links above for context.