Skip to content

Fix multipart uploads on retry#3484

Open
fallintoplace wants to merge 2 commits into
openai:mainfrom
fallintoplace:fix/replay-multipart-uploads
Open

Fix multipart uploads on retry#3484
fallintoplace wants to merge 2 commits into
openai:mainfrom
fallintoplace:fix/replay-multipart-uploads

Conversation

@fallintoplace

@fallintoplace fallintoplace commented Jul 10, 2026

Copy link
Copy Markdown
  • I understand that this repository is auto-generated and my pull request may not be merged

Changes being requested

Multipart requests currently reuse file objects across retries without rewinding them. A non-seekable stream is therefore empty on the second attempt, and a successful retry can make the upload appear to have succeeded with an empty file.

This change makes multipart bodies replayable for both sync and async clients:

  • non-seekable streams are copied into a spooled temporary file before the first send when a retry can occur, spilling to disk above 8 MiB
  • requests with retries disabled and normal API-key auth continue streaming files directly
  • seekable streams are rewound before each retry
  • temporary files are closed after the request finishes
  • workload identity 401 refresh retries rewind the same request body before resending it

Regression coverage exercises HTTP 500 responses, connection errors, timeouts, seekable streams, disabled retries, and workload identity 401 refreshes in both sync and async paths.

Additional context & links

Validated with the full client test module (187 tests), Ruff, Pyright, and mypy.

@fallintoplace fallintoplace requested a review from a team as a code owner July 10, 2026 20:31

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5c842c4440

ℹ️ 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".

Comment thread src/openai/_files.py

buffered = cast(IO[bytes], tempfile.SpooledTemporaryFile(max_size=_SPOOLED_FILE_MAX_SIZE))
try:
shutil.copyfileobj(file, buffered)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid spooling when retries are disabled

Because ReplayableFiles is constructed unconditionally before _request_with_retries reads max_retries, this copy now drains every non-seekable multipart upload into a temporary file even when the caller set max_retries=0 and is using normal API-key auth, where there is no retry path to replay. Large pipe/socket/generated uploads that previously streamed directly can now block until EOF or fill temporary storage; please only spool non-seekable streams when a retry or auth-retry can actually occur.

Useful? React with 👍 / 👎.

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.

1 participant