Skip to content

fix(tui): exit cleanly when native text allocation fails - #51387

Closed
YoshKoz wants to merge 1 commit into
anomalyco:v2from
YoshKoz:tui-alloc-exit
Closed

YoshKoz wants to merge 1 commit into
anomalyco:v2from
YoshKoz:tui-alloc-exit

Conversation

@YoshKoz

@YoshKoz YoshKoz commented Sep 25, 2026

Copy link
Copy Markdown

Issue for this PR

Closes #35053

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

The TUI crashes with Failed to create TextBuffer when the native renderer can no longer allocate a text or editor buffer (#35053). Today the error boundary catches that failure and renders the full error screen. That screen allocates more text buffers, so it can fail during the same render and take the TUI down while the terminal is left broken.

This PR treats the native text and editor allocation failures as fatal: isFatalRendererAllocationError matches the five allocation errors thrown by @opentui/core (TextBuffer, TextBufferView, EditorView, EditBuffer, SyntaxStyle). When the boundary catches one, it records the error, skips the error screen (returns null), and destroys the renderer once so the terminal is restored. The recorded error is then printed to stderr and the process exits with a nonzero status (process.exitCode is only raised when it is not already a failure). Ordinary render errors keep the existing error screen and exit status.

This does not fix the underlying allocation failure; it makes the failure exit cleanly with the original error instead of crashing again while drawing the error screen.

How did you verify your code works?

  • bun typecheck in packages/tui passes.
  • bun test test/util/error.test.ts passes (new classifier test).
  • bun test test/app-lifecycle.test.tsx passes the four new lifecycle tests (fatal exit nonzero, existing failure status preserved, competing destroy, ordinary error unchanged) and the existing tests. The only failures are the same six pre-existing unrelated failures present on unmodified v2 on this machine (Windows): keeps the prompt display stable..., execution failure keeps the empty session composer..., and four server plugin failures... cases.
  • The tests inject the reported error through the renderer tree and assert the terminal title is cleared, the renderer is destroyed once, stderr contains the original error, and the exit code is nonzero.

Screenshots / recordings

N/A (terminal behavior change, no visual output).

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

When the native renderer cannot allocate a text or editor buffer, the error boundary previously tried to draw the full error screen. That screen allocates more text buffers, so it could fail again and surface an unhandled error while the terminal was left in a broken state.

Classify the native text and editor allocation failures, skip the error screen for them, restore the terminal, print the original error to stderr, and exit with a nonzero status. Ordinary render errors keep the existing error screen and exit status.

Closes #35053
@github-actions

Copy link
Copy Markdown
Contributor

Thanks for your contribution!

This PR doesn't have a linked issue. All PRs must reference an existing issue.

Please:

  1. Open an issue describing the bug/feature (if one doesn't exist)
  2. Add Fixes #<number> or Closes #<number> to this PR description

See CONTRIBUTING.md for details.

@github-actions

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

@YoshKoz

YoshKoz commented Sep 25, 2026

Copy link
Copy Markdown
Author

The issue link is in the ### Issue for this PR\ section (\Closes #35053), so this looks like a false positive from the workflow, not a missing reference.

Cause: \pr-standards.yml\ uses \pull_request_target, so it runs the copy on the default branch (\dev). \dev's copy relies on \closingIssuesReferences, which GitHub only populates for PRs targeting the default branch, and it does not contain the description fallback that \�2's copy has. \CONTRIBUTING.md\ says to base on \�2, so I have left the base as \�2. Other v2 PRs (#51385, #51355, #51352, #51337, #51314, #51313) show the same
eeds:issue\ label.

Could a maintainer clear
eeds:issue\ here?

@YoshKoz YoshKoz closed this by deleting the head repository Oct 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant