Skip to content

fix(codex): avoid quadratic app-server input buffering - #8605

Merged
juliusmarminge merged 2 commits into
mainfrom
t3code/fix-app-server-stdin-buffering
Aug 29, 2026
Merged

fix(codex): avoid quadratic app-server input buffering#8605
juliusmarminge merged 2 commits into
mainfrom
t3code/fix-app-server-stdin-buffering

Conversation

@juliusmarminge

@juliusmarminge juliusmarminge commented Aug 29, 2026

Copy link
Copy Markdown
Member

Closes #5389

What Changed

Updated Codex app-server JSONL parsing to retain incomplete input as fragments and scan each incoming chunk once, avoiding quadratic buffering for large messages. Added coverage for large fragmented notifications, UTF-8 and CRLF framing, and malformed final lines. Documented the framing behavior.

Why

Large app-server messages could require repeated concatenation and splitting of the pending input, causing quadratic processing and degraded performance. Fragment-based buffering preserves framing correctness while keeping parsing efficient.

UI Changes

Not applicable.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Note

Medium Risk
Changes core wire-protocol framing for all Codex app-server stdin traffic; behavior is heavily tested but mistakes could break large payloads or stream shutdown.

Overview
Fixes quadratic stdin buffering in makeCodexAppServerPatchedProtocol when large JSONL messages arrive in many small chunks.

Incomplete lines are kept as a fragment array and each decoded chunk is scanned once for \n, instead of repeatedly concatenating the full pending buffer and splitting it. Complete lines are joined from fragments, trailing \r is stripped, and the tail stays fragmented until the next chunk or stream end.

On input stream close, any leftover fragments are joined and passed through handleLine (including parse errors for truncated JSON) before normal termination handling.

Tests cover a ~4MB notification split into 1KB chunks, JSONL/UTF-8/CRLF framing at chunk sizes 1/7/1024, and malformed fragmented response lines that fail the pending request.

Reviewed by Cursor Bugbot for commit d310c20. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Fix quadratic input buffering in makeCodexAppServerPatchedProtocol line assembly

Replaces the Ref<string> remainder with a local Array<string> fragment buffer in the stdin stream consumer. Each chunk is scanned once for newlines; completed lines are emitted by joining fragments, and only the unfinished tail is retained—avoiding repeated string concatenation across thousands of fragmented chunks.

  • At stream termination, any remaining fragments are now unconditionally joined and passed to handleLine, including when the remainder is empty or whitespace-only.
  • Adds tests covering large fragmented notifications, JSONL framing across varied chunk sizes, and malformed final-line error propagation.
  • Risk: handleLine is now called once more at termination with a possibly empty string; any handler that assumes it only receives non-empty content may behave differently.

Macroscope summarized d310c20.

- Preserve fragmented JSONL messages efficiently across stdin chunks
- Cover large messages, UTF-8, CRLF, and malformed final lines
@coderabbitai

coderabbitai Bot commented Aug 29, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c1b524ff-de67-4067-b7cb-e10b9b568dd7

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Aug 29, 2026
@github-actions

github-actions Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire 13.3 KiB 13.3 KiB +18 B (+0.1%) 15.1 KiB
Codex Thread snapshot wire 6.9 KiB 6.9 KiB +1 B (+0.0%) 7.3 KiB
Codex Live turn WebSocket wire 6.4 KiB 6.5 KiB +17 B (+0.3%) 7.8 KiB
Codex Live turn WebSocket decoded 55.6 KiB 55.6 KiB 0 B (0.0%) 66.4 KiB
Codex Live turn messages 11 11 0 (0.0%) 21
Claude Total thread wire 13.4 KiB 13.4 KiB +5 B (+0.0%) 15.1 KiB
Claude Thread snapshot wire 6.9 KiB 6.9 KiB +2 B (+0.0%) 7.3 KiB
Claude Live turn WebSocket wire 6.5 KiB 6.5 KiB +3 B (+0.0%) 7.8 KiB
Claude Live turn WebSocket decoded 56.4 KiB 56.4 KiB 0 B (0.0%) 66.4 KiB
Claude Live turn messages 11 11 0 (0.0%) 21

Baseline: 2bc9e8e · PR result: d310c20 · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 109.4 KiB
  • Claude decoded thread snapshot: 110.1 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

@macroscopeapp

macroscopeapp Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at d310c20

Macroscope's review found this PR approvable — This is a focused Codex protocol performance fix that makes fragmented JSONL buffering linear while retaining existing framing and termination behavior. The production logic is small and isolated, with targeted tests covering large payloads, UTF-8/CRLF boundaries, and malformed final input.

Notes:

  • No code objects were reviewed. Approvability was decided on eligibility alone.

You can add or adjust custom eligibility rules. Learn more.

@juliusmarminge
juliusmarminge merged commit 702a6ad into main Aug 29, 2026
25 checks passed
@juliusmarminge
juliusmarminge deleted the t3code/fix-app-server-stdin-buffering branch August 29, 2026 01:17
AspireOne pushed a commit to AspireOne/t3code that referenced this pull request Aug 29, 2026
bcotrim pushed a commit to bcotrim/mognet that referenced this pull request Aug 30, 2026
github-actions Bot added a commit to omarcresp/t3code-flake that referenced this pull request Aug 31, 2026
## What's Changed
* Remove Messages Glass Lab experiment by @juliusmarminge in pingdotgg/t3code#8599
* Require human review for pull requests changing product defaults by @juliusmarminge in pingdotgg/t3code#8603
* fix(codex): avoid quadratic app-server input buffering by @juliusmarminge in pingdotgg/t3code#8605
* fix(mobile): stabilize iOS header item transitions by @juliusmarminge in pingdotgg/t3code#8607
* chore(mobile): upgrade to Expo SDK 57 by @juliusmarminge in pingdotgg/t3code#8609
* fix(mobile): harden native header toolbar items by @juliusmarminge in pingdotgg/t3code#8611
* fix(server): stop querying Claude context usage after turns by @t3dotgg in pingdotgg/t3code#8610
* chore: vouch ryanrhughes by @t3dotgg in pingdotgg/t3code#8613
* feat(web): attach PDFs, ZIPs, and other files to a turn by @t3dotgg in pingdotgg/t3code#8236
* feat(web): keybinding settings as settings rows by @StiensWout in pingdotgg/t3code#8532
* feat: let an environment publish themes as a file by @ryanrhughes in pingdotgg/t3code#8569
* fix(web): clean up provider settings list and editor by @StiensWout in pingdotgg/t3code#8504
* fix(web): keep project picker popup inside the sidebar by @SunkenInTime in pingdotgg/t3code#8627
* fix(mobile): prevent header overflow and back-button artifacts by @juliusmarminge in pingdotgg/t3code#8624
* fix(server): retry automatic thread title generation by @Bil0000 in pingdotgg/t3code#8087
* fix(client-runtime): refresh edited pull request comments by @Bil0000 in pingdotgg/t3code#8094
* fix(web): four composer spacing defects by @Bil0000 in pingdotgg/t3code#8090
* perf(desktop): skip duplicate browser updates by @Bil0000 in pingdotgg/t3code#8018
* fix(web): render nested markdown images correctly by @flamboh in pingdotgg/t3code#8501
* fix(web): unify activity logs and composer banners by @juliusmarminge in pingdotgg/t3code#8693
* fix(mobile): reduce dev-client reload and Metro startup cost by @juliusmarminge in pingdotgg/t3code#8694
* revert(web): restore previous composer banners by @t3dotgg in pingdotgg/t3code#8733
* test(web): remove tests for unreachable helpers by @t3-code[bot] in pingdotgg/t3code#8738
* feat(mobile): update tool summaries and chat transitions by @juliusmarminge in pingdotgg/t3code#8793
* feat(web): play video attachments in chat by @Bil0000 in pingdotgg/t3code#8688
* fix(web,mobile): snooze menu no longer offers the same wake time twice by @vitalyiegorov in pingdotgg/t3code#8741
* fix(grok): allow model changes in existing threads by @ahmed-besic in pingdotgg/t3code#8392
* feat(mobile): pick, share, and receive files in threads by @t3dotgg in pingdotgg/t3code#8237
* fix(web): reduce title bar scroll fade height by @maria-rcks in pingdotgg/t3code#8799
* fix(windows): strip quotes from repaired PATH by @UtkarshUsername in pingdotgg/t3code#8746
* fix(web): open agent images in expanded preview by @maria-rcks in pingdotgg/t3code#8807
* fix(git): follow repository instructions in generated source control text by @maria-rcks in pingdotgg/t3code#8804
* fix(server): stop overpricing cached Claude tokens by @SunkenInTime in pingdotgg/t3code#8806
* fix(web): keep image preview above sidebar control by @maria-rcks in pingdotgg/t3code#8811
* fix(web): keep right panel synced with agent edits by @maria-rcks in pingdotgg/t3code#8803
* fix(web,mobile): render Codex citations and artifact templates by @Yash-Singh1 in pingdotgg/t3code#8584
* chore: add Windows setup script to t3.json by @UtkarshUsername in pingdotgg/t3code#8814
* fix(web): fold interim turn responses by @maria-rcks in pingdotgg/t3code#8828
* fix(web): use circle alert for failed tool calls by @maria-rcks in pingdotgg/t3code#8840
* feat(mobile): add offline iPhone voice input by @t3dotgg in pingdotgg/t3code#8614
* fix(web): prevent pull request metadata overlap by @MatthewFeroz in pingdotgg/t3code#8790

## New Contributors
* @ryanrhughes made their first contribution in pingdotgg/t3code#8569
* @ahmed-besic made their first contribution in pingdotgg/t3code#8392
* @MatthewFeroz made their first contribution in pingdotgg/t3code#8790

**Full Changelog**: pingdotgg/t3code@v0.0.36...v0.0.37

Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M 30-99 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: app-server stdin reader is quadratic in line length — OOM crash on large tool payloads

1 participant