Skip to content

[python-fastapi] type binary multipart fields as UploadFile#23793

Open
zswf-mle wants to merge 1 commit into
OpenAPITools:masterfrom
zswf-mle:fix/python-fastapi-binary-multipart-upload
Open

[python-fastapi] type binary multipart fields as UploadFile#23793
zswf-mle wants to merge 1 commit into
OpenAPITools:masterfrom
zswf-mle:fix/python-fastapi-binary-multipart-upload

Conversation

@zswf-mle
Copy link
Copy Markdown

@zswf-mle zswf-mle commented May 14, 2026

Fixes #20115.

Problem

The python-fastapi server generator typed multipart/form-data fields with format: binary using the client-side bytes union — Union[StrictBytes, StrictStr, Tuple[StrictStr, StrictBytes]] — and bound them via Form(None, ...). FastAPI parses such fields into UploadFile instances at request time, so Pydantic rejected valid uploads with HTTP 422 (Input should be a valid bytes / Input should be a valid string).

Fix

  • PythonFastAPIServerCodegen now overrides x-py-typing for isFormParam && isFile parameters: UploadFile when required, Optional[UploadFile] otherwise. It also injects from fastapi import File, UploadFile into the operation imports when at least one such parameter is present.
  • endpoint_argument_definition.mustache emits File(...) (with ... as the default for required file params, None for optional) instead of Form(None, ...) when the parameter is a binary form file.
  • The abstract base class signature follows automatically via param_type.mustache, which already reads x-py-typing.

Before / after

Before:

file: Annotated[Optional[Union[StrictBytes, StrictStr, Tuple[StrictStr, StrictBytes]]], Field(description="file to upload")] = Form(None, description="file to upload")

After:

file: Optional[UploadFile] = File(None, description="file to upload")

The client-side python generators are untouched — they still use the bytes-union for outbound multipart calls.

Tests / samples

  • Added testBinaryMultipartFieldUsesUploadFile plus a minimal issue_20115.yaml fixture covering both required and optional binary form fields. Asserts UploadFile / Optional[UploadFile] typing, File(...) / File(None, ...) defaults, the from fastapi import File, UploadFile import on both api.py and _base.py, and the absence of the legacy bytes-union.
  • Regenerated samples/server/petstore/python-fastapi/. The only diff is the upload_file endpoint and its imports in pet_api.py and pet_api_base.py.
  • mvn -pl modules/openapi-generator test -Dtest=PythonFastAPIServerCodegenTest — 6/6 pass.

PR checklist

  • Read the contribution guidelines.
  • Pull Request title clearly describes the work in the pull request and Pull Request description provides details about how to validate the work.
  • Run ./mvnw clean package, regenerated samples/server/petstore/python-fastapi/, and committed the changes. (Scoped to the python-fastapi generator; happy to widen the regen if maintainers want it.)
  • File the PR against master.
  • Reference the reported issue (fixes #20115).
  • @mention Python technical committee: @cbornet @tomplus @krjakbrjak @fa0311 @multani — cc @krjakbrjak as the original python-fastapi generator author.

Summary by cubic

Fix binary multipart form parameters in the python-fastapi server generator by typing them as UploadFile and binding with File(...) instead of Form(...). This prevents HTTP 422 errors on valid uploads and matches FastAPI’s request parsing.

  • Bug Fixes
    • For form file params, set x-py-typing to UploadFile or Optional[UploadFile].
    • Use File(...)/File(None, ...) in endpoint signatures; no longer use Form(...) for files.
    • Add from fastapi import File, UploadFile when needed.
    • Add tests for required/optional file fields and update the petstore sample. Client generators are unchanged.

Written for commit a6e84f1. Summary will update on new commits.

Multipart binary form fields were generated with the client-side bytes
union (Union[StrictBytes, StrictStr, Tuple[StrictStr, StrictBytes]])
and bound via Form(None, ...), which rejected the UploadFile instances
FastAPI parses out of multipart bodies and returned HTTP 422.

For isFormParam && isFile parameters, override x-py-typing to
UploadFile (or Optional[UploadFile] when not required), emit File(...)
instead of Form(None, ...) in the route signature, and inject
from fastapi import File, UploadFile.

Fixes OpenAPITools#20115
Copy link
Copy Markdown
Contributor

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

Choose a reason for hiding this comment

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

No issues found across 6 files

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] [Python-fastapi] File input incorrectly generated with FastAPI Form

2 participants