Skip to content

fix(app): a saved compare tab opens again, and a pane that breaks stays in its pane - #149

Merged
sean-brydon merged 1 commit into
mainfrom
fix/compare-tab-restore
Oct 18, 2026
Merged

sean-brydon merged 1 commit into
mainfrom
fix/compare-tab-restore

Conversation

@sean-brydon

Copy link
Copy Markdown
Collaborator

Fixes #137.

Why the window stayed grey

Any saved Compare tab crashed the app before it drew anything, on every launch. sanitize in lib/workspaces.ts runs when the module loads, and for Compare tabs it called mapLeaves, a const declared further down the file and not yet initialised (TypeError: Qf is not a function in the build). React hadn't mounted, so no error boundary could catch it. This explains the details in the issue: it happens whichever tab is active, it survives restarts, and removing the Compare tab fixes it. The bug has been there since v0.3.7.

Separately, PaneLayer draws every pane of every open workspace, but it sat outside the view's error boundary. A crash in any pane, such as the 0.3.22 chat hook bug fixed in 8d81e62, replaced the whole window with "Try again".

What changed

  • lib/restore.ts (new, pure, unit-tested) restores berth.workspaces and never throws.
    • Every workspace, tab, split and pane is checked.
    • A pane that can't be drawn is dropped, and the other side of its split takes its place.
    • A malformed Compare tab becomes a plain tab of its panes.
    • Fields of the wrong type take their defaults, and duplicate ids are dropped.
    • A compile-time check plus a round-trip test make sure a new pane kind can't be silently left out of saves.
  • Every pane has its own error boundary (PaneGuard). A side of a Compare tab that breaks offers "Show both terminals" and "Close tab"; other panes offer "Show its terminal" and "Close pane".
  • The tab bar and Compare bar each get a one-line error fallback.
  • The last-resort screen offers "Reset this tab" and "Close this tab", and has a strip to drag the window by.

Proof (mock mode)

A saved Compare tab of two chats opens again:

One side crashes (a test crash via ?mock&crash=), and the bar, the other side, the tabs and the sidebar keep working:

After "Show both terminals":

The tab bar's one-line fallback, then the last-resort screen and the app after "Close this tab" (both from temporary throws, reverted):


Tests

  • app/src/lib/restore.test.ts: 13 tests. pnpm test: 536 pass.
  • app/e2e/restore-tabs.spec.ts: 6 tests that seed the issue's saved state. 60/60 passed at --repeat-each=10. On main's code, 5 of the 6 fail with "Qf is not a function".
  • typecheck:plugins, check:titles, check:csp, check:themes, build and tsc -p e2e pass.
  • e2e/compare.spec.ts flakes with several workers in parallel (the Diff lane count is 0). It does the same on main.

🤖 Generated with Claude Code

…ys in its pane

Quitting with a Compare tab open left every later launch on an empty dark grey window (#137). The saved workspaces were tidied at import time by a function that, for Compare tabs only, called a helper declared further down the module, so the app threw before React drew anything, whichever tab was in front. Restoring now lives in lib/restore.ts, which checks every field of the save and drops what can't be drawn instead of throwing.

Every pane, the Compare bar, the tab bar and the pane layer now have their own error boundary. A pane that throws says so in its place with a way out (its terminal, the Terminal lane, or closing the tab), while the sidebar and the other tabs keep working; before, PaneLayer sat outside every boundary but the root one, so any pane in any open tab took the whole window. The last-resort screen offers to reset or close the tab showing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
berth Ready Ready Preview Oct 18, 2026 4:53pm UTC
berth-docs Ready Ready Preview Oct 18, 2026 4:53pm UTC

Request Review

@sean-brydon
sean-brydon merged commit 126320f into main Oct 18, 2026
8 checks passed
@linear-code

linear-code Bot commented Oct 18, 2026

Copy link
Copy Markdown

ENG-6404

This branch was successfully deployed

2 active deployments
Preview – berth-docs — 615d136e Deployed Oct 18, 2026 by vercel[bot]
Preview – berth — 615d136e Deployed Oct 18, 2026 by vercel[bot]
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.

Blank window persists across restarts after comparing two agent attempts

1 participant