fix(function_schema): raise UserError for Pydantic-reserved parameter names#3548
fix(function_schema): raise UserError for Pydantic-reserved parameter names#3548devteamaegis wants to merge 1 commit into
Conversation
… names Pydantic's create_model() treats 'model_config', 'model_fields', and 'model_computed_fields' as model-level config keys rather than fields. Passing a FieldInfo for those names caused a TypeError inside Pydantic's ConfigWrapper.for_model() with no actionable error message. Add a pre-flight check that raises UserError before calling create_model() whenever a function parameter uses one of these reserved names. Fixes openai#3547
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f0daa2dc24
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| # keys rather than fields (e.g. 'model_config', 'model_fields'). Passing | ||
| # a FieldInfo for those names causes a TypeError deep inside Pydantic, so | ||
| # we reject them early with a clear message. | ||
| _PYDANTIC_RESERVED_NAMES = {"model_config", "model_fields", "model_computed_fields"} |
There was a problem hiding this comment.
Include current Pydantic protected method names
With the repo pinned to Pydantic >=2.12.2, Pydantic's default protected namespaces are ('model_validate', 'model_dump') (see https://docs.pydantic.dev/latest/api/config/#pydantic.config.ConfigDict.protected_namespaces), and fields that exactly collide with existing BaseModel members still raise from Pydantic during create_model. Because this new reserved-name guard omits model_validate and model_dump, a tool like def f(model_dump: str) still bypasses the intended UserError and surfaces a lower-level Pydantic exception; please include those current protected member names in the early check as well.
Useful? React with 👍 / 👎.
What's broken
Calling
function_schema()(or@function_tool) on a function with a parameter namedmodel_configcrashes with aTypeError: 'FieldInfo' object is not iterabledeep inside Pydantic. The same applies tomodel_fieldsandmodel_computed_fields. The error gives no indication of what went wrong or how to fix it.Why it happens
Pydantic's
create_model()treatsmodel_configas a model-level configuration key rather than a field. Whenfunction_schema.pypasses aFieldInfofor that name,ConfigWrapper.for_model()calls.update()on theFieldInfoobject expecting a dict, which crashes.Fix
Added a small set
_PYDANTIC_RESERVED_NAMES = {"model_config", "model_fields", "model_computed_fields"}and a guard at the start of the field-building loop infunction_schema(). If a parameter name matches, aUserErroris raised immediately with a clear message explaining the conflict and asking the user to rename the parameter. Change is 12 lines in one file.Test
Added
test_pydantic_reserved_param_name_raises_user_errortotests/test_function_schema.py. It defines a function with amodel_config: strparameter and asserts thatfunction_schema()raisesUserErrorwith a message matching "reserved by Pydantic".Fixes #3547