iTranslated by AI
Bypassing Type Checks with Pydantic's mypy Plugin and alias_generator
Summary
- Extra keys and missing required fields were slipping through due to the combination of Pydantic's mypy plugin and
alias_generator. - In mypy, there is no configuration to detect both simultaneously.
- I changed the setup to detect extra keys by removing the plugin. Most of the plugin's benefits can be covered at runtime.
- While
tycan detect both at the same time, the stable version is not yet available (planned for 2026).
Confirmed Versions
- Python: 3.14.2
- Pydantic: 2.12.5
- mypy: 1.19.1
- ty: 0.0.13
Background
One day, while performing a code review, I found some code that clearly had issues but had passed the CI.
from pydantic import BaseModel, ConfigDict
from pydantic.alias_generators import to_camel
class Response(BaseModel):
model_config = ConfigDict(alias_generator=to_camel)
name: str
age: int
Response(db_session="db_session", name="name") # db_session? What about age?
A DB session was being packed into a REST API response—I thought, "What's going on?"—and then I realized required fields were also missing. Wait, wasn't mypy supposed to be used for exactly these kinds of checks?
Cause
Upon investigation, I found the following behavior:
| Condition | Extra keys | Missing required fields |
|---|---|---|
| Without plugin | Detected | Passed through |
Without plugin + alias_generator
|
Detected | Passed through |
| With plugin | Passed through | Detected |
With plugin + alias_generator
|
Passed through | Passed through |
In short, no configuration exists in mypy to detect both simultaneously.
Without the plugin, Pydantic's __init__ signature is not recognized, so required field checks do not work.
On the other hand, enabling the plugin respects Pydantic's default extra="ignore" setting, allowing extra keys to pass through.
Furthermore, using alias_generator disables required field checks even when the plugin is enabled.
Since alias_generator is a function evaluated at runtime, static analysis has no way of knowing what the argument names will be.
The plugin is forced to generate a signature that accepts **kwargs, resulting in all checks being effectively disabled.
In this case, because the plugin was enabled while using alias_generator, both issues were passing through.
$ mypy sample.py --config-file /dev/null # with alias_generator + without plugin
error: Unexpected keyword argument "db_session" for "Response" # Only extra keys are detected
Is the Pydantic mypy plugin necessary?
The main benefits of the plugin are:
- Required field checks can be performed
- Field changes in frozen models can be detected
- Untyped fields can be warned about during model definition
- Simultaneous specification of
Field'sdefaultanddefault_factorycan be detected - Arguments for
model_constructcan be type-checked
However, as seen in this case, there is a disadvantage where the check for extra keys becomes lenient.
Furthermore, when combined with alias_generator, even the useful required field checks stop working.
The official documentation states the following:
Pydantic works well with mypy right out of the box.
However, Pydantic also ships with a mypy plugin that adds a number of important Pydantic-specific features that improve its ability to type-check your code.
Essentially, the stance is "It works without it, but it's convenient to have it."
In the End, What Did I Do?
I removed the plugin.
When I checked the features listed as benefits of the plugin, I found that most of them were already covered at runtime.
- "Required field checks" ->
ValidationError - "Detection of changes to frozen models" ->
ValidationError - "Warnings for untyped fields" ->
PydanticUserError - "Simultaneous specification of
defaultanddefault_factory" ->TypeError
The only thing that cannot be detected at runtime is the type checking for model_construct, but since it is a special method for skipping validation, its frequency of use is low.
With this, I can now detect the extra keys that were previously passing through when the plugin was enabled. Although the omission of required fields still cannot be detected by mypy, I decided to tolerate this because it results in a ValidationError at runtime.
ty Can Handle Both
I also tried ty, a type checker currently under development by Astral (the developers of Ruff and uv).
$ ty check sample.py
error[missing-argument]: No argument provided for required parameter `age`
error[unknown-argument]: Argument `db_session` does not match any known parameter
While mypy could only detect one or the other, ty can handle both.
Previously, there was a note stating "not ready for production use," but that description disappeared with the Beta version release in December 2025. However, since the Stable version is not yet out (as of January 2026), I'll be waiting eagerly for it.
Personally, I wish it had a name that was a bit easier to search for...
Bonus: Why Can ty Detect It?
I was curious about "Why can ty detect both in the first place?" so I looked into it.
The Existence of @dataclass_transform
Pydantic's BaseModel has the @dataclass_transform decorator (PEP 681) attached to its metaclass. This was added in Python 3.11 to tell type checkers, "Please treat this class like a dataclass."
ty looks at this decorator and infers the __init__ signature from the model's field definitions. That's why it can detect both extra keys and missing required fields.
Also, as of January 2026, ty was in the middle of implementing Pydantic support. In other words, it doesn't yet know about the existence of alias_generator and doesn't make extra allowances, so it performs type checking based solely on the field definitions.
The behavior might change once official support is fully implemented, so I will update this content as soon as I can confirm.
Discussion