Skip to content

fix(python-fastapi): relax strict typing for path/query/header params (#21905)#24098

Open
Goopher wants to merge 2 commits into
OpenAPITools:masterfrom
Goopher:fix/python-fastapi-query-param-strict-coercion
Open

fix(python-fastapi): relax strict typing for path/query/header params (#21905)#24098
Goopher wants to merge 2 commits into
OpenAPITools:masterfrom
Goopher:fix/python-fastapi-query-param-strict-coercion

Conversation

@Goopher

@Goopher Goopher commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Pydantic strict types (StrictInt/StrictStr/StrictFloat) and Field(strict=True) disable automatic string coercion. Since path/query/header values always arrive on the wire as strings, FastAPI rejected otherwise-valid requests with a 422 (int_type: Input should be a valid integer).

This adds a relaxStrict flag to PydanticType that emits coercible types (int/str/float) and omits strict=True, gated behind a new shouldRelaxStrictParameterTyping() hook that defaults to false. PythonFastAPIServerCodegen overrides it for path/query/header params. Body params and the Python client generator are unchanged — strict typing is correct for JSON bodies.

Regenerated the python-fastapi petstore sample. Verified the python client, flask, aiohttp, blueplanet, and httpx samples regenerate with zero diff, confirming the shared-base change is inert for non-fastapi generators.

Fixes #21905

PR checklist

  • Read the contribution guidelines.
  • Run the following to build the project and update samples:
    ./mvnw clean package || exit
    ./bin/generate-samples.sh ./bin/configs/*.yaml || exit
    ./bin/utils/export_docs_generators.sh || exit
    
    Commit all changed files.
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.

Python technical committee — @cbornet @tomplus @krjakbrjak @fa0311 @multani (@krjakbrjak as the python-fastapi generator author).

https://claude.ai/code/session_019g7iwAyg7ErX1WrhqHyTn6


Summary by cubic

Relax strict typing for path, query, and header parameters in the python-fastapi server generator so FastAPI can coerce wire-string values and avoid 422 errors. Body params and models stay strict. Fixes #21905.

  • Bug Fixes

    • Emit int/str/float (no strict=True) for path/query/header params to allow coercion.
    • Regenerated the python-fastapi petstore sample; other generators are unchanged.
  • Refactors

    • Replaced the relaxStrict flag and shouldRelaxStrictParameterTyping() with PydanticCoercibleType and a getPydanticParameterType() factory.
    • PythonFastAPIServerCodegen returns PydanticCoercibleType for path/query/header params and the strict base type for others; shared types in AbstractPythonCodegen made protected for extension.

Written for commit 4decf3c. Summary will update on new commits.

Review in cubic

…OpenAPITools#21905)

Pydantic strict types (StrictInt/StrictStr/StrictFloat) and Field(strict=True)
disable automatic string coercion. Since path/query/header values always arrive
on the wire as strings, FastAPI rejected otherwise-valid requests with a 422
(int_type: Input should be a valid integer).

Add a relaxStrict flag to PydanticType that emits coercible types (int/str/float)
and omits strict=True, gated behind a shouldRelaxStrictParameterTyping() hook that
defaults to false. PythonFastAPIServerCodegen overrides it for path/query/header
params. Body params and the Python client generator are unchanged (strict typing
is correct for JSON bodies).

Regenerated the python-fastapi petstore sample.

Claude-Session: https://claude.ai/code/session_019g7iwAyg7ErX1WrhqHyTn6

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 10 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="samples/server/petstore/python-fastapi/src/openapi_server/apis/store_api_base.py">

<violation number="1" location="samples/server/petstore/python-fastapi/src/openapi_server/apis/store_api_base.py:5">
P2: Unused `StrictInt` import remains after strict type relaxation — should be removed to avoid F401 lint failures in generated code.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

from typing import ClassVar, Dict, List, Tuple # noqa: F401

from pydantic import Field, StrictInt, StrictStr
from pydantic import Field, StrictInt

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Unused StrictInt import remains after strict type relaxation — should be removed to avoid F401 lint failures in generated code.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/server/petstore/python-fastapi/src/openapi_server/apis/store_api_base.py, line 5:

<comment>Unused `StrictInt` import remains after strict type relaxation — should be removed to avoid F401 lint failures in generated code.</comment>

<file context>
@@ -2,7 +2,7 @@
 from typing import ClassVar, Dict, List, Tuple  # noqa: F401
 
-from pydantic import Field, StrictInt, StrictStr
+from pydantic import Field, StrictInt
 from typing import Any, Dict
 from typing_extensions import Annotated
</file context>
Suggested change
from pydantic import Field, StrictInt
from pydantic import Field

@Mattias-Sehlstedt

Copy link
Copy Markdown
Contributor

Rather than expanding the responsibilities of PythonType with relaxStrict and a number of logical branches here and there, would it make more sense to create a concrete "QueryParameterType" class/object that clearly signaled that those parameter types abide to entirely different rules?

Currently we have a whole essay to try to describe the background about the coercion that occurs and when, but I believe it is always better to capture the relations and the rules as explicit code-structures (read, separation-of-responsibilities).

My understanding is that the server-bound parameters never should utilize the strictness that Pydantic offers, and if that is the case then I believe it would be valuable to show that in a more explicit way than "remember to always set this variable to true for query parameters since it changes to typing to not be the strict types".

Replace the relaxStrict boolean + shouldRelaxStrictParameterTyping hook with
an explicit PydanticCoercibleType subclass of PydanticType that never emits
Pydantic strict types for the scalar kinds where strictness blocks coercion.

Selection moves into a getPydanticParameterType() factory: PythonFastAPIServer
returns PydanticCoercibleType for path/query/header params and the strict base
type for everything else. The rule ("wire-string params are never strict") is
now a code structure rather than a flag callers must remember to set, and the
explanatory comment lives in one place on the class it describes.

Behaviour-preserving: the regenerated python-fastapi sample is byte-identical
to the previous commit. Python codegen tests (fastapi, client) pass.

Claude-Session: https://claude.ai/code/session_019g7iwAyg7ErX1WrhqHyTn6
@Goopher

Goopher commented Jun 22, 2026

Copy link
Copy Markdown
Contributor Author

@Mattias-Sehlstedt, updated to have a separate class for params.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG][Python] strict=True in Pydantic Field breaks HTTP query parameter type conversion for integers

2 participants