Pydantic v2

You can use the extra field in the model_config class attribute to forbid extra attributes during model initialisation (by default, additional attributes will be ignored).

For example:

from pydantic import BaseModel, ConfigDict

class Pet(BaseModel):
    model_config = ConfigDict(extra="forbid")

    name: str

data = {
    "name": "some name",
    "some_extra_field": "some value",
}

my_pet = Pet.model_validate(data)   # <- effectively the same as Pet(**pet_data)

will raise a ValidationError:

ValidationError: 1 validation error for Pet
some_extra_field
  Extra inputs are not permitted [type=extra_forbidden, input_value='some value', input_type=str]
    For further information visit https://errors.pydantic.dev/2.7/v/extra_forbidden

Works as well when the model is "nested", e.g.:

class PetModel(BaseModel):
    my_pet: Pet
    n: int

pet_data = {
    "my_pet": {"name": "Some Name", "invalid_field": "some value"},
    "n": 5,
}

pet_model = PetModel.model_validate(pet_data)
# Effectively the same as
# pet_model = PetModel(my_pet={"name": "Some Name", "invalid_field": "some value"}, n=5)

will raise:

ValidationError: 1 validation error for PetModel
my_pet.invalid_field
  Extra inputs are not permitted [type=extra_forbidden, input_value='some value', input_type=str]
    For further information visit https://errors.pydantic.dev/2.7/v/extra_forbidden

NB: As you can see, extra has the type ExtraValues now, and its value will get validated by ConfigDict. This means it's not possible to accidentally provide an unsupported value for extra (e.g. having a typo), i.e. something like ConfigDict(extra="fordib") will fail with a SchemaError.

Pydantic v1

You can use the extra field in the Config class to forbid extra attributes during model initialisation (by default, additional attributes will be ignored).

For example:

from pydantic import BaseModel, Extra

class Pet(BaseModel):
    name: str

    class Config:
        extra = Extra.forbid

data = {
    "name": "some name",
    "some_extra_field": "some value",
}

my_pet = Pet.parse_obj(data)   # <- effectively the same as Pet(**pet_data)

will raise a VaidationError:

ValidationError: 1 validation error for Pet
some_extra_field
  extra fields not permitted (type=value_error.extra)

Works as well when the model is "nested", e.g.:

class PetModel(BaseModel):
    my_pet: Pet
    n: int

pet_data = {
    "my_pet": {"name": "Some Name", "invalid_field": "some value"},
    "n": 5,
}

pet_model = PetModel.parse_obj(pet_data)
# Effectively the same as
# pet_model = PetModel(my_pet={"name": "Some Name", "invalid_field": "some value"}, n=5)

will raise:

ValidationError: 1 validation error for PetModel
my_pet -> invalid_field
  extra fields not permitted (type=value_error.extra)
Answer from Paul P on Stack Overflow
🌐
OpenAI Developer Community
community.openai.com › api
additionalProperties error when unpacking list of one pydantic object in Union - API - OpenAI Developer Community
September 24, 2024 - I kept getting additionalProperties error when using pydantic SDK object for response format: openai.BadRequestError: Error code: 400 - {‘error’: {‘message’: “Invalid schema for response_format ‘PlanDecision’: In context=(‘properties’, ‘Action_input’), ‘additionalProperties’ is required to be supplied and to be false.”, ‘type’: ‘invalid_request_error’, ‘param’: ‘response_format’, ‘code’: None}}. Also this error only happened when trying to unpack a list of pydantic object inside an Union: Union...
🌐
GitHub
github.com › pydantic › pydantic › issues › 6082
explicit additionalProperties even when model_config["extra"] != "forbid" · Issue #6082 · pydantic/pydantic
June 11, 2023 - Due to the evaluation of missing ... "extra" - "ignore", "allow" as well. pydantic defaults to "ignore", swallowing additional data not defined in the model instead of reporting an error....
Author   commonism
🌐
Pydantic
docs.pydantic.dev › latest › api › config
Configuration - Pydantic Validation
Defaults to False. ... Whether to strip leading and trailing whitespace for str types. ... The minimum length for str types. Defaults to None. ... The maximum length for str types. Defaults to None. ... Whether to ignore, allow, or forbid extra data during model initialization. Defaults to 'ignore'. ... from pydantic import BaseModel, ConfigDict class User(BaseModel): model_config = ConfigDict(extra='ignore') # (1)!
🌐
GitHub
github.com › samuelcolvin › pydantic › issues › 3505
Extra.forbid hides existing additionalProperties on models with __root__: Dict · Issue #3505 · pydantic/pydantic
December 9, 2021 - Model: DictModel Annotations: typing.Dict[str, typing.List[int]] Schema: { "title": "DictModel", "type": "object", "additionalProperties": { "type": "array", "items": { "type": "integer" } } } Model: ForbiddenDict Annotations: typing.Dict[str, typing.List[int]] Schema: { "title": "ForbiddenDict", "type": "object", "additionalProperties": false }
Author   tsnowlan
🌐
Medium
medium.com › @aviadr1 › how-to-fix-openai-structured-outputs-breaking-your-pydantic-models-bdcd896d43bd
How to Fix OpenAI Structured Outputs Breaking Your Pydantic Models | by aviad rozenhek | Medium
August 14, 2025 - class Config(BaseModel): settings: ... "additionalProperties": {} # Empty schema = OpenAI explosion } OpenAI requires additionalProperties to either be false or have a proper type....
Top answer
1 of 3
71

Pydantic v2

You can use the extra field in the model_config class attribute to forbid extra attributes during model initialisation (by default, additional attributes will be ignored).

For example:

from pydantic import BaseModel, ConfigDict

class Pet(BaseModel):
    model_config = ConfigDict(extra="forbid")

    name: str

data = {
    "name": "some name",
    "some_extra_field": "some value",
}

my_pet = Pet.model_validate(data)   # <- effectively the same as Pet(**pet_data)

will raise a ValidationError:

ValidationError: 1 validation error for Pet
some_extra_field
  Extra inputs are not permitted [type=extra_forbidden, input_value='some value', input_type=str]
    For further information visit https://errors.pydantic.dev/2.7/v/extra_forbidden

Works as well when the model is "nested", e.g.:

class PetModel(BaseModel):
    my_pet: Pet
    n: int

pet_data = {
    "my_pet": {"name": "Some Name", "invalid_field": "some value"},
    "n": 5,
}

pet_model = PetModel.model_validate(pet_data)
# Effectively the same as
# pet_model = PetModel(my_pet={"name": "Some Name", "invalid_field": "some value"}, n=5)

will raise:

ValidationError: 1 validation error for PetModel
my_pet.invalid_field
  Extra inputs are not permitted [type=extra_forbidden, input_value='some value', input_type=str]
    For further information visit https://errors.pydantic.dev/2.7/v/extra_forbidden

NB: As you can see, extra has the type ExtraValues now, and its value will get validated by ConfigDict. This means it's not possible to accidentally provide an unsupported value for extra (e.g. having a typo), i.e. something like ConfigDict(extra="fordib") will fail with a SchemaError.

Pydantic v1

You can use the extra field in the Config class to forbid extra attributes during model initialisation (by default, additional attributes will be ignored).

For example:

from pydantic import BaseModel, Extra

class Pet(BaseModel):
    name: str

    class Config:
        extra = Extra.forbid

data = {
    "name": "some name",
    "some_extra_field": "some value",
}

my_pet = Pet.parse_obj(data)   # <- effectively the same as Pet(**pet_data)

will raise a VaidationError:

ValidationError: 1 validation error for Pet
some_extra_field
  extra fields not permitted (type=value_error.extra)

Works as well when the model is "nested", e.g.:

class PetModel(BaseModel):
    my_pet: Pet
    n: int

pet_data = {
    "my_pet": {"name": "Some Name", "invalid_field": "some value"},
    "n": 5,
}

pet_model = PetModel.parse_obj(pet_data)
# Effectively the same as
# pet_model = PetModel(my_pet={"name": "Some Name", "invalid_field": "some value"}, n=5)

will raise:

ValidationError: 1 validation error for PetModel
my_pet -> invalid_field
  extra fields not permitted (type=value_error.extra)
2 of 3
20

The preferred solution is to use a ConfigDict (ref. the documentation):

from pydantic import BaseModel, ConfigDict

class Pet(BaseModel):
    model_config = ConfigDict(extra='forbid')

    name: str

Paul P's answer still works (for now), but the Config class has been deprecated in pydantic v2.0. Another deprecated solution is pydantic.Extra.forbid.

One advantage of the method above is that it can be type checked.

🌐
GitHub
github.com › pydantic › pydantic-ai › issues › 1469
pydantic-ai Gemini Schema Generation Fails for Dynamically Created Models with List[KeyValuePair] Replacement for Dict · Issue #1469 · pydantic/pydantic-ai
April 13, 2025 - The top-level schema correctly has "additionalProperties": False. ... Despite the Pydantic-generated schema appearing correct, the error Unexpected error running agent: Additional properties in JSON Schema are not supported by Gemini occurs ...
Author   talkingtoaj
🌐
GitHub
github.com › openai › openai-python › issues › 2740
Improper handling of pydantic `extra="allow"` · Issue #2740 · openai/openai-python
November 8, 2025 - The response_format option requires "additionalProperties": false to be present in the json schema that is submitted. When using Pydantic models, setting the extra="allow" option causes the json schema return addtionalProperties=True.
Author   lucaswiman
🌐
GitHub
github.com › pydantic › pydantic › discussions › 5853
Defining additional properties with a given schema · pydantic/pydantic · Discussion #5853
{ "type": "object", "properties": { "age": { "type": "number" } }, "required": ["age"], "additionalProperties": { "type": "object", "properties": { "data": { "type": "str" } } } } ... Thanks 😊 So additional properties are allowed as long as they adhere to a given schema, thanks! Beta Was this translation helpful? Give feedback. ... from typing import Any from pydantic import BaseModel, model_validator class Model(BaseModel, extra="allow"): model_config = dict( json_schema_extra={ "additionalProperties": { "type": "object", "properties": {"data": {"type": "str"}}, } } ) age: float @model_validator(mode="before") @classmethod def validate_additional_properties(cls, v: Any) -> Any: if isinstance(v, dict): errors = {} for k, value in v.items(): if k != "age" and isinstance(value,
Author   pydantic
Find elsewhere
🌐
OpenAI Developer Community
community.openai.com › api
Unexpected additionalProperties requirement for nested Pydantic models in response_format - API - OpenAI Developer Community
March 25, 2025 - I’m encountering an error when using the following Pydantic model as response_schema in the API. The error only occurs with specific nested models, but not others that appear to have a similar structure. Here’s the model: from enum import Enum from typing import List, Optional from pydantic import BaseModel, Field class ElementCategory(str, Enum): visual = "visual" audio = "audio" class DetailLevel(str, Enum): minimal = "minimal" moderate = "moderate" class ModelApproach(Bas...
🌐
GitHub
github.com › koxudaxi › datamodel-code-generator › issues › 2368
Pydantic deprecation warning due to class-based config and use of Extra when using additionalProperties: false · Issue #2368 · koxudaxi/datamodel-code-generator
March 29, 2025 - Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.10/migration/ warnings.warn(DEPRECATION_MESSAGE, DeprecationWarning) ... { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Foo", "type": "object", "properties": { "foo": { "type": "string" } }, "required": ["foo"], "additionalProperties": false }
Author   trajano
🌐
Pydantic
pydantic.dev › articles › pydantic-v2-12-release
Announcement: Pydantic v2.12 Release
October 7, 2025 - The additionalProperties JSON Schema keyword will be populated depending on the closed/extra_items specification (False if closed, True if extra_items is Any or object, matching the schema of the extra_items type otherwise).
🌐
GitHub
github.com › pydantic › pydantic-ai › issues › 1888
Pydantic-AI warning when using 'dict' as parameter in a tool with Gemini (2.5, 2.0 Flash) · Issue #1888 · pydantic/pydantic-ai
June 2, 2025 - python3.13/site-packages/pydantic_ai/profiles/google.py:37: UserWarning: `additionalProperties` is not supported by Gemini; it will be removed from the tool JSON schema. Full schema: {'additionalProperties': False, 'properties': {'params': {'additionalProperties': True, 'type': 'object'}}, 'required': ['params'], 'type': 'object'} Source of additionalProperties within the full schema: {'type': 'object', 'additionalProperties': True} If this came from a field with a type like `dict[str, MyType]`, that field will always be empty.
Author   devorboy
🌐
Readthedocs
autodoc-pydantic.readthedocs.io › en › stable › users › examples.html
Examples — autodoc_pydantic 2.2.0 documentation
Applies like wise\nto pydantic models.", "type": "object", "properties": { "field_without_default": { "title": "Field Without Default", "type": "string" }, "field_plain_with_validator": { "default": 100, "title": "Field Plain With Validator", "type": "integer" }, "BarFoo": { "default": "FooBar", "title": "Barfoo", "type": "string" }, "field_with_constraints_and_description": { "default": 5, "description": "Shows constraints within doc string.", "maximum": 100, "minimum": 0, "title": "Field With Constraints And Description", "type": "integer" } }, "additionalProperties": false, "required": [ "f
🌐
GitHub
github.com › openai › openai-python › issues › 1659
Apply more fixes for Pydantic schema incompatibilities with OpenAI structured outputs · Issue #1659 · openai/openai-python
August 17, 2024 - Use ISO 8601 to format this value.") publisher: Optional[Publisher] = Field(None, description="The publisher of the article") class Config: json_schema_extra = { "additionalProperties": False } class NewsArticles(BaseModel): query: str = Field(description="The query used to search for news articles") articles: List[Article] = Field(description="The list of news articles returned by the query") class Config: json_schema_extra = { "additionalProperties": False } def test_schema_compatible(): client = OpenAI() # build on the internals that the openai client uses to clean up the pydantic schema fo
Author   mcantrell
🌐
Pydantic
docs.pydantic.dev › latest › concepts › types
Types - Pydantic Validation
from pydantic import TypeAdapter type Json = dict[str, Json] | list[Json] | str | int | float | bool | None # (1)! ta = TypeAdapter(Json) print(ta.json_schema()) """ { '$defs': { 'Json': { 'anyOf': [ { 'additionalProperties': {'$ref': '#/$defs/Json'}, 'type': 'object', }, {'items': {'$ref': '#/$defs/Json'}, 'type': 'array'}, {'type': 'string'}, {'type': 'integer'}, {'type': 'number'}, {'type': 'boolean'}, {'type': 'null'}, ] } }, '$ref': '#/$defs/Json', } """
🌐
PyPI
pypi.org › project › pydantic
pydantic · PyPI
Always include additionalProperties: True for arbitrary dictionary schemas by @austinyu in #11392 · Expose fallback parameter in serialization methods by @Viicos in #11398 · Fix path serialization behavior by @sydney-runkle in #11416 ... Pydantic v2.11 is a version strongly focused on build ...
      » pip install pydantic
    
Published   Nov 26, 2025
Version   2.12.5
🌐
GitHub
github.com › openai › openai-python › issues › 2004
Pydantic conversion logic for structured outputs is broken for models containing dictionaries · Issue #2004 · openai/openai-python
January 10, 2025 - import json from typing import ... additionalProperties: False into the resulting JSON schema definition, meaning that the dictionary must always be empty: { "properties": { "arguments": { "description": "The arguments to pass to the ...
Author   dbczumar
Top answer
1 of 3
44

Pydantic extra fields behaviour was updated in their 2.0 release. Per their docs, you now don't need to do anything but set the model_config extra field to allow and then can use the model_extra field or __pydantic_extra__ instance attribute to get a dict of extra fields.

from pydantic import BaseModel, Field, ConfigDict


class Model(BaseModel):
    python_name: str = Field(alias="name")

    model_config = ConfigDict(
        extra='allow',
    )

m = Model(**{"name": "Name", "address": "bla bla", "post": "post"}).model_extra
assert m == {'address': 'bla bla', 'post': 'post'}

m = Model(**{"name": "Name", "foobar": "fizz"}).__pydantic_extra__
assert m == {'foobar': 'fizz'}

m = Model(**{"name": "Name"}).__pydantic_extra__
assert m == {}
2 of 3
40

NOTE: This answer applies to version Pydantic 1.x. See robcxyz's answer for a 2.x solution.


From the pydantic docs:

extra

whether to ignore, allow, or forbid extra attributes during model initialization. Accepts the string values of 'ignore', 'allow', or 'forbid', or values of the Extra enum (default: Extra.ignore). 'forbid' will cause validation to fail if extra attributes are included, 'ignore' will silently ignore any extra attributes, and 'allow' will assign the attributes to the model.

This can either be included in the model Config class, or as arguments when inheriting BaseModel.

from pydantic import BaseModel, Extra

class BaseModel(BaseModel, extra=Extra.allow):
    name: str


model = Model.parse_obj(
   {"name": "Name", "address": "bla bla", "post": "post"}
)

print(model)
# name='Name' post='post' address='bla bla'

To get the extra values you could do something simple, like comparing the set of __fields__ defined on the class to the values in __dict__ on an instance:

class Model(BaseModel, extra=Extra.allow):
    python_name: str = Field(alias="name")

    @property
    def extra_fields(self) -> set[str]:
        return set(self.__dict__) - set(self.__fields__)
>>> Model.parse_obj({"name": "Name", "address": "bla bla", "post": "post"}).extra_fields
{'address', 'post'}
>>> Model.parse_obj({"name": "Name", "foobar": "fizz"}).extra_fields
{'foobar'}
>>> Model.parse_obj({"name": "Name"}).extra_fields
set()