Skip to content

fix(provider-transport-fetch): bound SSE buffer to prevent OOM#96989

Merged
vincentkoc merged 5 commits into
openclaw:mainfrom
wangmiao0668000666:fix/bound-anthropic-sse-parse-buffer
Jun 27, 2026
Merged

fix(provider-transport-fetch): bound SSE buffer to prevent OOM#96989
vincentkoc merged 5 commits into
openclaw:mainfrom
wangmiao0668000666:fix/bound-anthropic-sse-parse-buffer

Conversation

@wangmiao0668000666

@wangmiao0668000666 wangmiao0668000666 commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

src/agents/provider-transport-fetch.ts has two unbounded memory paths in sanitizeOpenAISdkSseResponse:

  1. SSE sanitizer: Accumulates decoded chunks into a buffer string that only drains when a \n\n SSE event boundary is found. If data arrives without boundaries, the buffer grows unboundedly.

  2. JSON-to-SSE synthesis: Accumulates raw JSON bytes while synthesizing SSE frames, with no cumulative cap.

Non-OK SSE gap (fixed in this PR): Non-ok SSE responses previously bypassed ALL byte caps via an early !response.ok return, leaving the SDK error-body response.text() path unbounded — the same OOM vector.

Changes

  • src/agents/provider-transport-fetch.ts — Add SSE_SYNTHESIZE_JSON_MAX_BYTES (16 MiB) and SSE_SANITIZE_BUFFER_MAX_BYTES (64 KiB). Cap the SSE sanitizer buffer after event-drain loop. Cap the JSON synthesis total bytes. Cap non-ok SSE bodies via createBoundedStream. Cancel upstream reader on overflow.
  • src/agents/provider-transport-fetch.test.ts — 77 tests (was 73): add coalesced-valid-chunk regression test, oversized non-ok SSE regression test.
  • No new abstraction — createBoundedStream is local to the file.

Real behavior proof

  • Behavior addressed: Both ok and non-ok SSE responses through sanitizeOpenAISdkSseResponse are now bounded. The SSE sanitizer buffer caps at 64 KiB between event boundaries. The JSON synthesis caps at 16 MiB total. Non-ok SSE bodies cap at 16 MiB.
  • Real environment tested: Linux x86_64, Node 22, vitest 4.1.8
  • Exact steps: pnpm test src/agents/provider-transport-fetch.test.ts --run
  • Evidence after fix: 77/77 tests pass. Coalesced-chunk test verifies valid data >64 KiB with event boundaries does not false-fire the cap. Non-ok oversized SSE test verifies upstream cancel + bounded bytes.
  • Observed result: Ok + non-ok SSE bodies bounded at configured caps. Valid data with event boundaries unaffected.
  • What was not tested: Live provider API endpoints (would not reproduce a hostile oversized body without Content-Length — mock fetch with ReadableStream is the correct abstraction).

Risk checklist

  • User-visible behavior change? Only for inputs exceeding the caps (malicious or buggy endpoints). Normal SSE responses are unaffected.
  • Config/env/migration change? No.
  • Security/auth/secrets/network/tool-execution change? Yes — OOM/DoS protection for SSE response handling.
  • Highest-risk area: False positive on valid large SSE payloads. The 64 KiB inter-boundary buffer cap matches event-boundary delimiters found in well-formed SSE. The 16 MiB total caps match existing PROVIDER_JSON_RESPONSE_MAX_BYTES precedent.

@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: S labels Jun 26, 2026
@wangmiao0668000666

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper

clawsweeper Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed June 26, 2026, 8:50 PM ET / 00:50 UTC.

Summary
Adds 64 KiB SSE-tail and 16 MiB JSON-synthesis caps in src/agents/provider-transport-fetch.ts, plus regression tests for oversized malformed streams and valid coalesced SSE events.

PR surface: Source +31, Tests +127. Total +158 across 2 files.

Reproducibility: yes. Current main source shows delimiter-free SSE and streaming JSON responses can accumulate without a cap, and the PR body includes after-fix terminal output from a real node:http proof script; I did not run tests in this read-only review.

Review metrics: 1 noteworthy metric.

  • Stream failure thresholds: 2 added: 64 KiB SSE tail cap, 16 MiB JSON synthesis cap. These thresholds define when provider streams now fail closed instead of continuing to buffer, so maintainers should notice them before merge.

Stored data model
Persistent data-model change detected: serialized state: src/agents/provider-transport-fetch.test.ts. Confirm migration or upgrade compatibility proof before merge.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🦞 diamond lobster
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P2] Record maintainer acceptance of the thresholds, or tune the constants before merge.

Risk before merge

  • [P1] Existing custom OpenAI-compatible providers or proxies that emit an unterminated SSE event over 64 KiB or a streaming JSON body over 16 MiB will now fail closed instead of continuing to buffer.
  • [P1] The real-server proof covers malformed/OOM shapes and valid controls, but maintainers still need to decide whether those thresholds are acceptable for supported custom-provider payloads.

Maintainer options:

  1. Accept The Fail-Closed Caps (recommended)
    Land after maintainers agree that a 64 KiB unterminated SSE tail and a 16 MiB synthesized JSON body are outside supported provider behavior.
  2. Tune Thresholds Before Landing
    Adjust the constants and matching tests first if maintainers know a supported custom provider needs larger event tails or JSON streaming bodies.
  3. Pause For Shared Guard Cleanup
    Pause this PR only if maintainers want one shared stream-cap helper across the related hardening PRs before taking more file-local caps.

Next step before merge

  • No automated repair is needed; maintainers need to accept or adjust the compatibility and availability thresholds before merge.

Security
Cleared: No supply-chain, permissions, secret-handling, sandboxing, or external-code-execution concern was found; the diff adds local stream caps and focused tests.

Review details

Best possible solution:

Land the focused caps after maintainers accept the fail-closed thresholds, or tune the constants first if known supported providers need larger payloads.

Do we have a high-confidence way to reproduce the issue?

Yes. Current main source shows delimiter-free SSE and streaming JSON responses can accumulate without a cap, and the PR body includes after-fix terminal output from a real node:http proof script; I did not run tests in this read-only review.

Is this the best way to solve the issue?

Yes, with a maintainer threshold decision. The patch caps the exact accumulators, preserves complete SSE event framing, and cancels upstream readers on overflow; a shared byte-guard helper is a cleanup alternative, not required for this fix.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 5880e0afc4dc.

Label changes

Label justifications:

  • P2: This is a normal-priority provider transport availability hardening PR with limited blast radius and no line-level correctness blocker found.
  • merge-risk: 🚨 compatibility: Existing custom-provider or proxy responses above the new SSE-tail or synthesized-JSON thresholds can now fail instead of streaming through.
  • merge-risk: 🚨 availability: If a real provider crosses the new caps, the agent request fails closed rather than continuing to stream or buffer.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The PR body includes copied terminal output from a real node:http proof script exercising oversized SSE/JSON overflow, valid controls, and a negative control after the patch.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes copied terminal output from a real node:http proof script exercising oversized SSE/JSON overflow, valid controls, and a negative control after the patch.
Evidence reviewed

PR surface:

Source +31, Tests +127. Total +158 across 2 files.

View PR surface stats
Area Files Added Removed Net
Source 1 31 0 +31
Tests 1 127 0 +127
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 2 158 0 +158

What I checked:

  • Repository policy read: Root and scoped agent policy were read fully; the review applied the repository requirements for whole-path review, sibling-surface checks, dependency contract inspection, and compatibility-risk treatment. (AGENTS.md:13, 5880e0afc4dc)
  • Current-main JSON synthesis is unbounded: On current main, streaming JSON synthesis appends decoded chunks into one buffer until EOF before emitting SSE, with no byte cap in that loop. (src/agents/provider-transport-fetch.ts:123, 5880e0afc4dc)
  • Current-main SSE tail is unbounded: On current main, the SSE sanitizer appends text into buffer and returns when no event boundary exists, so an unterminated response can grow without a cap. (src/agents/provider-transport-fetch.ts:156, 5880e0afc4dc)
  • PR head caps both accumulators: PR head adds SSE_SYNTHESIZE_JSON_MAX_BYTES and SSE_SANITIZE_BUFFER_MAX_BYTES, checks the JSON byte total before appending the next chunk, checks the SSE tail only after complete event draining, and cancels the upstream reader on overflow. (src/agents/provider-transport-fetch.ts:49, b8c7ae1ea8b9)
  • PR head has focused regression coverage: The added tests cover a large coalesced valid SSE chunk, an oversized delimiter-free SSE body, and oversized streaming JSON synthesis. (src/agents/provider-transport-fetch.test.ts:1133, b8c7ae1ea8b9)
  • OpenAI SDK dependency contract checked: OpenAI SDK v6.39.1 Stream.fromSSEResponse uses _iterSSEMessages, whose iterSSEChunks accumulates bytes until a double newline boundary before yielding a chunk, matching the sanitizer boundary invariant this PR protects. (openai-node/src/core/streaming.ts:257)

Likely related people:

  • vincentkoc: Authored the split-SSE sanitizer fix in the same file, authored maintainer commits in the merged sibling stream-bound PR, and added the latest tightening commit on this PR branch. (role: recent adjacent contributor; confidence: high; commits: 9e549a89db83, ceb723b0758c, 5a996811d220; files: src/agents/provider-transport-fetch.ts, src/agents/provider-transport-fetch.test.ts, src/agents/streaming-byte-guard.ts)
  • jiahjian: Authored the recent already-SSE JSON-content-type sanitizer fix touching the same function and tests. (role: recent area contributor; confidence: medium; commits: 27ae5cc55992; files: src/agents/provider-transport-fetch.ts, src/agents/provider-transport-fetch.test.ts)
  • aaajiao: Authored the missing-content-type streamed response fix in the same guarded fetch path and provided live endpoint proof for that compatibility boundary. (role: adjacent contract contributor; confidence: medium; commits: 0b55180690f0; files: src/agents/provider-transport-fetch.ts, src/agents/provider-transport-fetch.test.ts)
  • ly-wang19: Local blame on this shallow checkout attributes the current file snapshot to a broad update PR that copied the current provider transport files into the checkout, though it is not clear semantic ownership of this sanitizer. (role: recent broad area contributor; confidence: low; commits: a0e9ca1e9544; files: src/agents/provider-transport-fetch.ts, src/agents/provider-transport-fetch.test.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. labels Jun 26, 2026
@wangmiao0668000666

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

P1 findings addressed:

  1. Moved SSE cap after complete-event draining — check runs only on unterminated tail (enqueueSanitized), not on full chunk.
  2. Cancel upstream reader on BOTH overflow paths (SSE sanitizer + JSON synthesis) before controller.error().
  3. Added coalesced-valid-chunk regression test: 500 SSE events in one TCP chunk (no cap false-positive).

Commit: 521e302

@clawsweeper

clawsweeper Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. labels Jun 26, 2026
@wangmiao0668000666

Copy link
Copy Markdown
Contributor Author

Removed unused encoder declaration from the coalesced SSE test (line 1136 in the previous diff). Lint and tests all pass.

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Jun 26, 2026
@vincentkoc
vincentkoc force-pushed the fix/bound-anthropic-sse-parse-buffer branch from 261c96e to b8c7ae1 Compare June 27, 2026 00:45
wangmiao0668000666 added a commit to wangmiao0668000666/openclaw that referenced this pull request Jun 27, 2026
…law#96989)

* fix(provider-transport-fetch): bound SSE buffer to prevent OOM

* fix(provider-transport-fetch): appease oxlint curly rule in test

* fix(provider-transport-fetch): drain events before cap + cancel reader on overflow

* fix(provider-transport-fetch): remove unused encoder from coalesced chunk test

Co-Authored-By: Claude <[email protected]>

* fix(transport): tighten SSE buffer guards

---------

Co-authored-by: Claude <[email protected]>
Co-authored-by: Vincent Koc <[email protected]>
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jun 27, 2026
…law#96989)

* fix(provider-transport-fetch): bound SSE buffer to prevent OOM

* fix(provider-transport-fetch): appease oxlint curly rule in test

* fix(provider-transport-fetch): drain events before cap + cancel reader on overflow

* fix(provider-transport-fetch): remove unused encoder from coalesced chunk test

Co-Authored-By: Claude <[email protected]>

* fix(transport): tighten SSE buffer guards

---------

Co-authored-by: Claude <[email protected]>
Co-authored-by: Vincent Koc <[email protected]>
xydigit-zt pushed a commit to xydigit-zt/xydigit-zt-openclaw that referenced this pull request Jun 28, 2026
…law#96989)

* fix(provider-transport-fetch): bound SSE buffer to prevent OOM

* fix(provider-transport-fetch): appease oxlint curly rule in test

* fix(provider-transport-fetch): drain events before cap + cancel reader on overflow

* fix(provider-transport-fetch): remove unused encoder from coalesced chunk test

Co-Authored-By: Claude <[email protected]>

* fix(transport): tighten SSE buffer guards

---------

Co-authored-by: Claude <[email protected]>
Co-authored-by: Vincent Koc <[email protected]>
obviyus pushed a commit to Marvinthebored/openclaw that referenced this pull request Jun 30, 2026
The 64 KiB inter-event SSE sanitize buffer added in openclaw#96989 rejects a single
legitimate event larger than 64 KiB — e.g. a large gpt-5.5 reasoning summary on
the openai-chatgpt-responses API — throwing "SSE response exceeded max buffer
size (65536 bytes) without event boundary" and failing the whole request. The
default ChatGPT-subscription gpt-5.5 path is unusable (present in v2026.6.11-beta.1).

Decouple the two bounds: keep the non-OK error-body cap tight at 64 KiB
(SSE_NONOK_BODY_MAX_BYTES), and raise the inter-event sanitize buffer to the same
16 MiB ceiling as the JSON-synthesis path. The guard still trips on a genuinely
boundary-less (hostile/broken) stream, just not on a real large event.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
obviyus pushed a commit that referenced this pull request Jun 30, 2026
The 64 KiB inter-event SSE sanitize buffer added in #96989 rejects a single
legitimate event larger than 64 KiB — e.g. a large gpt-5.5 reasoning summary on
the openai-chatgpt-responses API — throwing "SSE response exceeded max buffer
size (65536 bytes) without event boundary" and failing the whole request. The
default ChatGPT-subscription gpt-5.5 path is unusable (present in v2026.6.11-beta.1).

Decouple the two bounds: keep the non-OK error-body cap tight at 64 KiB
(SSE_NONOK_BODY_MAX_BYTES), and raise the inter-event sanitize buffer to the same
16 MiB ceiling as the JSON-synthesis path. The guard still trips on a genuinely
boundary-less (hostile/broken) stream, just not on a real large event.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 1, 2026
The 64 KiB inter-event SSE sanitize buffer added in openclaw#96989 rejects a single
legitimate event larger than 64 KiB — e.g. a large gpt-5.5 reasoning summary on
the openai-chatgpt-responses API — throwing "SSE response exceeded max buffer
size (65536 bytes) without event boundary" and failing the whole request. The
default ChatGPT-subscription gpt-5.5 path is unusable (present in v2026.6.11-beta.1).

Decouple the two bounds: keep the non-OK error-body cap tight at 64 KiB
(SSE_NONOK_BODY_MAX_BYTES), and raise the inter-event sanitize buffer to the same
16 MiB ceiling as the JSON-synthesis path. The guard still trips on a genuinely
boundary-less (hostile/broken) stream, just not on a real large event.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
QiuYuang pushed a commit to QiuYuang/openclaw that referenced this pull request Jul 1, 2026
…law#96989)

* fix(provider-transport-fetch): bound SSE buffer to prevent OOM

* fix(provider-transport-fetch): appease oxlint curly rule in test

* fix(provider-transport-fetch): drain events before cap + cancel reader on overflow

* fix(provider-transport-fetch): remove unused encoder from coalesced chunk test

Co-Authored-By: Claude <[email protected]>

* fix(transport): tighten SSE buffer guards

---------

Co-authored-by: Claude <[email protected]>
Co-authored-by: Vincent Koc <[email protected]>
QiuYuang pushed a commit to QiuYuang/openclaw that referenced this pull request Jul 1, 2026
The 64 KiB inter-event SSE sanitize buffer added in openclaw#96989 rejects a single
legitimate event larger than 64 KiB — e.g. a large gpt-5.5 reasoning summary on
the openai-chatgpt-responses API — throwing "SSE response exceeded max buffer
size (65536 bytes) without event boundary" and failing the whole request. The
default ChatGPT-subscription gpt-5.5 path is unusable (present in v2026.6.11-beta.1).

Decouple the two bounds: keep the non-OK error-body cap tight at 64 KiB
(SSE_NONOK_BODY_MAX_BYTES), and raise the inter-event sanitize buffer to the same
16 MiB ceiling as the JSON-synthesis path. The guard still trips on a genuinely
boundary-less (hostile/broken) stream, just not on a real large event.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
chenyangjun-xy pushed a commit to chenyangjun-xy/openclaw that referenced this pull request Jul 1, 2026
…law#96989)

* fix(provider-transport-fetch): bound SSE buffer to prevent OOM

* fix(provider-transport-fetch): appease oxlint curly rule in test

* fix(provider-transport-fetch): drain events before cap + cancel reader on overflow

* fix(provider-transport-fetch): remove unused encoder from coalesced chunk test

Co-Authored-By: Claude <[email protected]>

* fix(transport): tighten SSE buffer guards

---------

Co-authored-by: Claude <[email protected]>
Co-authored-by: Vincent Koc <[email protected]>
chenyangjun-xy pushed a commit to chenyangjun-xy/openclaw that referenced this pull request Jul 1, 2026
The 64 KiB inter-event SSE sanitize buffer added in openclaw#96989 rejects a single
legitimate event larger than 64 KiB — e.g. a large gpt-5.5 reasoning summary on
the openai-chatgpt-responses API — throwing "SSE response exceeded max buffer
size (65536 bytes) without event boundary" and failing the whole request. The
default ChatGPT-subscription gpt-5.5 path is unusable (present in v2026.6.11-beta.1).

Decouple the two bounds: keep the non-OK error-body cap tight at 64 KiB
(SSE_NONOK_BODY_MAX_BYTES), and raise the inter-event sanitize buffer to the same
16 MiB ceiling as the JSON-synthesis path. The guard still trips on a genuinely
boundary-less (hostile/broken) stream, just not on a real large event.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
chenyangjun-xy pushed a commit to chenyangjun-xy/openclaw that referenced this pull request Jul 3, 2026
…law#96989)

* fix(provider-transport-fetch): bound SSE buffer to prevent OOM

* fix(provider-transport-fetch): appease oxlint curly rule in test

* fix(provider-transport-fetch): drain events before cap + cancel reader on overflow

* fix(provider-transport-fetch): remove unused encoder from coalesced chunk test

Co-Authored-By: Claude <[email protected]>

* fix(transport): tighten SSE buffer guards

---------

Co-authored-by: Claude <[email protected]>
Co-authored-by: Vincent Koc <[email protected]>
chenyangjun-xy pushed a commit to chenyangjun-xy/openclaw that referenced this pull request Jul 3, 2026
The 64 KiB inter-event SSE sanitize buffer added in openclaw#96989 rejects a single
legitimate event larger than 64 KiB — e.g. a large gpt-5.5 reasoning summary on
the openai-chatgpt-responses API — throwing "SSE response exceeded max buffer
size (65536 bytes) without event boundary" and failing the whole request. The
default ChatGPT-subscription gpt-5.5 path is unusable (present in v2026.6.11-beta.1).

Decouple the two bounds: keep the non-OK error-body cap tight at 64 KiB
(SSE_NONOK_BODY_MAX_BYTES), and raise the inter-event sanitize buffer to the same
16 MiB ceiling as the JSON-synthesis path. The guard still trips on a genuinely
boundary-less (hostile/broken) stream, just not on a real large event.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
wheakerd pushed a commit to wheakerd/clawdbot that referenced this pull request Jul 15, 2026
…law#96989)

* fix(provider-transport-fetch): bound SSE buffer to prevent OOM

* fix(provider-transport-fetch): appease oxlint curly rule in test

* fix(provider-transport-fetch): drain events before cap + cancel reader on overflow

* fix(provider-transport-fetch): remove unused encoder from coalesced chunk test

Co-Authored-By: Claude <[email protected]>

* fix(transport): tighten SSE buffer guards

---------

Co-authored-by: Claude <[email protected]>
Co-authored-by: Vincent Koc <[email protected]>
(cherry picked from commit 1bccd29)
wheakerd pushed a commit to wheakerd/clawdbot that referenced this pull request Jul 15, 2026
The 64 KiB inter-event SSE sanitize buffer added in openclaw#96989 rejects a single
legitimate event larger than 64 KiB — e.g. a large gpt-5.5 reasoning summary on
the openai-chatgpt-responses API — throwing "SSE response exceeded max buffer
size (65536 bytes) without event boundary" and failing the whole request. The
default ChatGPT-subscription gpt-5.5 path is unusable (present in v2026.6.11-beta.1).

Decouple the two bounds: keep the non-OK error-body cap tight at 64 KiB
(SSE_NONOK_BODY_MAX_BYTES), and raise the inter-event sanitize buffer to the same
16 MiB ceiling as the JSON-synthesis path. The guard still trips on a genuinely
boundary-less (hostile/broken) stream, just not on a real large event.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
(cherry picked from commit 81d60ca)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: S status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants