pydantic: Extra inputs are not permitted (tested)
Extra inputs are not permitted [type=extra_forbidden] means the model has extra="forbid" and the input contains a key that is not a field. With aliases, passing the Python field name instead of the alias also triggers it.
1. extra="ignore", "forbid", "allow"
from pydantic import BaseModel, ConfigDict, ValidationError
class Default(BaseModel):
name: str
class Strict(BaseModel):
model_config = ConfigDict(extra="forbid")
name: str
class Keep(BaseModel):
model_config = ConfigDict(extra="allow")
name: str
data = {"name": "pen", "colour": "red"}
print("default:", repr(Default(**data)), "-> extra silently ignored")
try:
Strict(**data)
except ValidationError as e:
print(e)
k = Keep(**data)
print("allow:", repr(k), "| model_extra:", k.model_extra)
Output:
default: Default(name='pen') -> extra silently ignored
1 validation error for Strict
colour
Extra inputs are not permitted [type=extra_forbidden, input_value='red', input_type=str]
For further information visit https://errors.pydantic.dev/2.14/v/extra_forbidden
allow: Keep(name='pen', colour='red') | model_extra: {'colour': 'red'}
By default Pydantic 2 ignores unknown keys. The error only appears when the model (or a parent class, or a shared base model) sets extra="forbid"; the line above the message is the unexpected key. Either remove that key from the input, add it as a field, or switch the model to "ignore" (drop it) or "allow" (keep it in model_extra).
2. The hidden cause: aliases
from pydantic import BaseModel, ConfigDict, Field, ValidationError
class User(BaseModel):
model_config = ConfigDict(extra="forbid")
user_name: str = Field(alias="userName")
for data in [{"userName": "ada"}, {"user_name": "ada"}]:
try:
print(data, "->", repr(User(**data)))
except ValidationError as e:
print(data, "->", [(x["type"], x["loc"]) for x in e.errors()])
class User2(BaseModel):
model_config = ConfigDict(extra="forbid", populate_by_name=True)
user_name: str = Field(alias="userName")
print("populate_by_name:", repr(User2(user_name="ada")))
Output:
{'userName': 'ada'} -> User(user_name='ada')
{'user_name': 'ada'} -> [('missing', ('userName',)), ('extra_forbidden', ('user_name',))]
populate_by_name: User2(user_name='ada')
With an alias, the input must use the alias (userName). Passing the Python field name (user_name) gives two errors at once: the alias is missing and the field name is an extra input. Send the alias, or set populate_by_name=True so both work.
Checklist
- Read the field name printed above "Extra inputs are not permitted": it is the key Pydantic did not expect.
- Look for
extra="forbid"on the model and on every base class. - Check aliases and camelCase/snake_case mismatches between the client and the model.
- In FastAPI the same error shows up as a 422 with
type: extra_forbidden.
Related: FastAPI 422 Unprocessable Entity ยท BaseSettings moved to pydantic-settings.
Frequently asked questions
Why does Pydantic say Extra inputs are not permitted?
The model sets extra='forbid' and the input has a key that is not a field. The key is printed on the line above the message.
Does Pydantic 2 forbid extra fields by default?
No. The default, extra='ignore', silently drops them. Only extra='forbid' raises.
Why do I get extra_forbidden for a field that exists?
It has an alias: input must use the alias. Passing the field name gives missing + extra_forbidden unless populate_by_name=True.
Written with AI assistance. Measured on 2026-10-23 with Pydantic 2.14.1 and Python 3.14.7 (python:3-alpine in Docker). Each block was run verbatim and the output pasted unedited. PlainHeaders is our extension; Python and Pydantic are free.