Skip to content

feat(websocket): recover queued binary frames after reconnect - #4191

Merged
markstuart-oai merged 3 commits into
mainfrom
markstuart/websocket-runtime-audit-20261027
Oct 28, 2026
Merged

markstuart-oai merged 3 commits into
mainfrom
markstuart/websocket-runtime-audit-20261027

Conversation

@markstuart-oai

@markstuart-oai markstuart-oai commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Summary

During reconnect, send_raw(bytes) used to decode queued bytes as UTF-8. A valid UTF-8 payload changed from a binary frame to a text frame. Other bytes raised UnicodeDecodeError before the SDK could send them.

Preserve each frame and its place in the queue. If recovery stops, unsent_frames returns the original text and bytes in order. unsent_messages retains its text-only compatibility list, including valid UTF-8 binary as text. Ordinary exception-attribute snapshots render a fixed redacted holder; explicit recovery access still returns the data.

Verification

The previous transport failed 28 wire cases against local WebSocket peers; the initial fix passed 357 queue, recovery and session tests and 328 URL and security tests. Sync and async tests cover all seven bindings.

On the current revision, 109 focused queue/reconnect/wire tests pass in both SDK copies, including attribute snapshots, recovery-list identity and writes, and assignment before parent initialization. Pinned Pyright and mypy pass on the changed source and tests; scoped Ruff and git diff checks pass. Hosted CI passes all eight required checks, including OkTest, and all 26 reported checks are clear.

Release

Release as a minor version. Pyright users whose subclasses redeclare unsent_messages: list[str] should remove that redundant declaration and use the inherited writable property. Runtime reads, mutation, assignment, and assignment before super().__init__ remain supported. This follows README's static-typing minor-release policy. A normal squash merge uses the current feat(websocket): PR title and selects the required minor release. If using rebase, preserve that feature classification in the merged commit history.

@github-actions

Copy link
Copy Markdown
Contributor

Castiron custom code

Evaluated main: 3596d18f05b63081fd64c6da82b515293afb98c6.

Trusted main policy: 3596d18f05b63081fd64c6da82b515293afb98c6.

✅ No new custom-code files detected.

0 mixed files remain; 0 existing customizations changed.

Compared 3596d18f05b6 → 194bc68cbb39. Generated baselines verified.

A changed generated baseline means this report cannot reliably identify which handwritten lines changed.

Inspect the custom-code diff

Download the exact patch produced by this run (requires repository access):

gh run download 40462487697 --repo openai/openai-python \
  --name castiron-custom-code-40462487697-1 --dir /tmp/castiron-custom-code-40462487697-1
git apply --stat /tmp/castiron-custom-code-40462487697-1/custom-code.patch
cat /tmp/castiron-custom-code-40462487697-1/custom-code.patch

Or reproduce it from an SDK checkout containing the vendored reporter:

git fetch --no-tags origin 3596d18f05b63081fd64c6da82b515293afb98c6 194bc68cbb390798bb1311f0368375a2fe65ac4a
python3 scripts/castiron/custom_code_report.py report \
  --base 3596d18f05b63081fd64c6da82b515293afb98c6 \
  --head 194bc68cbb390798bb1311f0368375a2fe65ac4a --target-branch main --fetch --require-head-hash --public \
  --out /tmp/castiron-custom-code-194bc68cbb39
cat /tmp/castiron-custom-code-194bc68cbb39/custom-code.patch

This is the current full custom patch for mixed files, not an attribution of only the handwritten lines changed by this PR.

Full report and patch

@markstuart-oai
markstuart-oai marked this pull request as ready for review October 27, 2026 17:50
@markstuart-oai
markstuart-oai requested a review from a team as a code owner October 27, 2026 17:50
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-28T06:39:07.585651Z 99fa41e New commits
🔒 Security Review ✅ Completed 2026-10-28T06:39:35.408520Z 99fa41e New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@markstuart-oai

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Another round soon, please!

Reviewed commit: 194bc68cbb

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

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: 194bc68cbb

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@markstuart-oai

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Chef's kiss.

Reviewed commit: 194bc68cbb

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

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: 194bc68cbb

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@jbeckwith-oai jbeckwith-oai 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.

Reviewed binary frame type/order preservation, queue byte accounting, sync/async reconnect behavior, and backward compatibility of unsent_messages alongside unsent_frames. No actionable findings.

Static review of commit 194bc68. Hosted checks show no failures (applicable checks passed; other jobs skipped). No local tests or candidate code were run.

@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: f073d8aed2

ℹ️ 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/_exceptions.py Outdated

@jbeckwith-oai jbeckwith-oai 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.

Correcting my earlier approval after validating the existing payload-retention finding: #4191 (comment) . I missed the repository's explicit requirement to keep sensitive request/customer data out of exceptions.

unsent_frames stores complete opaque binary request payloads directly on the exception. Normal exception text is safe, but reporters that collect exception attributes can retain those bytes. Keep recovery payloads outside the exception and expose safe metadata or a recovery handle; preserve the necessary recovery behavior. This is a P2 redaction/policy issue; no actual data disclosure was established. Referencing the existing thread instead of duplicating an inline comment.

The merge from main leaves the six feature files unchanged. Static re-review with an independent reviewer; no candidate code or local tests run. Applicable completed checks pass; Python 3.10/3.14 tests are still running.

@markstuart-oai markstuart-oai changed the title fix(websocket): preserve queued binary frames during reconnect feat(websocket): recover queued binary frames after reconnect Oct 28, 2026

@jbeckwith-oai jbeckwith-oai 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.

Re-reviewed the diagnostic-redaction fix with an independent static second pass. The slotted recovery holder now redacts ordinary exception-attribute snapshots while preserving explicit recovery, list identity, mutation, assignment, and legacy subclass initialization. This addresses my previous finding; no new actionable findings. Deliberate inspection of recovery properties is still explicit access to the caller's data.

Hosted checks show no failures; Python 3.14 remains running. No candidate code or tests run locally.

@markstuart-oai
markstuart-oai added this pull request to the merge queue Oct 28, 2026
Merged via the queue into main with commit f079868 Oct 28, 2026
26 checks passed
@markstuart-oai
markstuart-oai deleted the markstuart/websocket-runtime-audit-20261027 branch October 28, 2026 06:49
@openai-sdks openai-sdks Bot mentioned this pull request Oct 28, 2026
gh-actions-shared Bot pushed a commit to xf-qubit/openai-python that referenced this pull request Oct 28, 2026
Automated Release PR
---


##
[3.41.0](openai/openai-python@v3.40.0...v3.41.0)
(2026-10-28)


### Features

* **api:** accept typed references in Realtime response inputs
([openai#4189](openai#4189))
([8ecb487](openai@8ecb487))
* **api:** add response tool usage models
([openai#4201](openai#4201))
([55fc500](openai@55fc500))
* **api:** filter agent sessions by metadata
([openai#4200](openai#4200))
([77fd116](openai@77fd116))
* **websocket:** recover queued binary frames after reconnect
([openai#4191](openai#4191))
([f079868](openai@f079868))


### Bug Fixes

* **examples:** detect incomplete WebSocket responses
([openai#4187](openai#4187))
([8559299](openai@8559299))
* **examples:** handle interruptions and disconnects in push-to-talk
([openai#4192](openai#4192))
([35fc9f3](openai@35fc9f3))
* keep consumer fixtures clean under strict Pyright
([openai#4204](openai#4204))
([5012565](openai@5012565))


### Chores

* **api:** document upcoming model shutdowns
([openai#4199](openai#4199))
([5b43cce](openai@5b43cce))
* **api:** update image-model documentation
([openai#4198](openai#4198))
([fa67521](openai@fa67521))
* enforce generated-file ownership
([openai#4193](openai#4193))
([1b37b9a](openai@1b37b9a))
* migrate development type checking to ty
([openai#4202](openai#4202))
([45b9531](openai@45b9531))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: openai-sdks[bot] <284451331+openai-sdks[bot]@users.noreply.github.com>
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.

3 participants