diff --git a/src/openai/lib/_pydantic.py b/src/openai/lib/_pydantic.py index 3cfe224cb1..d4c18d2325 100644 --- a/src/openai/lib/_pydantic.py +++ b/src/openai/lib/_pydantic.py @@ -47,8 +47,14 @@ def _ensure_strict_json_schema( _ensure_strict_json_schema(definition_schema, path=(*path, "definitions", definition_name), root=root) typ = json_schema.get("type") - if typ == "object" and "additionalProperties" not in json_schema: - json_schema["additionalProperties"] = False + if typ == "object": + # Set additionalProperties to False for strict schema compliance, but preserve + # structured schemas (e.g., for Dict[str, T] which needs {"additionalProperties": {schema}}). + # The OpenAI API requires additionalProperties=false for structured output, + # even if Pydantic models use extra="allow" which sets it to True. + additional_props = json_schema.get("additionalProperties") + if additional_props is True or "additionalProperties" not in json_schema: + json_schema["additionalProperties"] = False # object types # { 'type': 'object', 'properties': { 'a': {...} } } diff --git a/tests/lib/test_pydantic.py b/tests/lib/test_pydantic.py index 754a15151c..f784921a7b 100644 --- a/tests/lib/test_pydantic.py +++ b/tests/lib/test_pydantic.py @@ -409,3 +409,29 @@ def test_nested_inline_ref_expansion() -> None: "additionalProperties": False, } ) + + +def test_pydantic_extra_allow() -> None: + """Test that models with extra='allow' correctly set additionalProperties to False. + + Regression test for issue #2740. + The OpenAI API requires additionalProperties=false for structured output, + even when Pydantic models use extra="allow" which generates True by default. + """ + from pydantic import ConfigDict + + class MyClassWithExtraAllow(BaseModel): + model_config = ConfigDict(extra="allow") + field: str = Field(description="A test field") + + schema = to_strict_json_schema(MyClassWithExtraAllow) + + assert schema == snapshot( + { + "properties": {"field": {"description": "A test field", "title": "Field", "type": "string"}}, + "required": ["field"], + "title": "MyClassWithExtraAllow", + "type": "object", + "additionalProperties": False, + } + )