Skip to content

fix(cli-kit): batch large output chunks to prevent event loop blocking#7008

Draft
alfonso-noriega wants to merge 1 commit intomainfrom
fix-stack-trace-overload
Draft

fix(cli-kit): batch large output chunks to prevent event loop blocking#7008
alfonso-noriega wants to merge 1 commit intomainfrom
fix-stack-trace-overload

Conversation

@alfonso-noriega
Copy link
Contributor

Problem

When a POS UI extension throws a large stack trace (3MB+), the entire output arrives as a single write() call to ConcurrentOutput's Writable stream. The synchronous processing — stripAnsi(), split(/\n/), and setProcessOutput with a spread of the full accumulated array — causes a render cycle expensive enough to block the Node.js event loop for several seconds. During that time, Ink's useInput hook cannot process keypresses, so q (quit) and p (preview) become unresponsive.

Reported via Dev Support: a developer building POS UI Extensions observed the CLI freezing on large stack traces during shopify app dev.

Fix

In ConcurrentOutput.tsx, the writableStream write handler now splits chunks exceeding MAX_LINES_PER_BATCH (100) lines into smaller batches. Each batch is scheduled via setImmediate, yielding to the event loop between renders so Ink's input handling can run between batches.

  • Chunks ≤ 100 lines: unchanged behaviour, next() called synchronously
  • Chunks > 100 lines: split into 100-line batches, scheduled with setImmediate between each, next() deferred until all batches are queued (backpressure preserved)

Test

Added a test that writes 250 lines as a single chunk and asserts all lines appear in the rendered output.

Checklist

  • Lint passes
  • Type check passes
  • Tests pass (12/12)

🤖 Generated with Claude Code

When a POS UI extension throws a large stack trace (3MB+), all lines
arrive as a single write to ConcurrentOutput's Writable stream. The
synchronous stripAnsi + split + React state update causes a long render
cycle that blocks the Node.js event loop, making keyboard shortcuts
(q, p) unresponsive.

Fix: split chunks exceeding 100 lines into batches and schedule each
via setImmediate, yielding to the event loop between renders so Ink's
useInput hook can process keypresses between batches.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Contributor

Coverage report

St.
Category Percentage Covered / Total
🟡 Statements 77.26% 14583/18876
🟡 Branches 70.89% 7232/10202
🟡 Functions 76.23% 3704/4859
🟡 Lines 78.74% 13782/17503

Test suite run success

3807 tests passing in 1462 suites.

Report generated by 🧪jest coverage report action from 585b600

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