Skip to content

fix(desktop): surface Buzz Term attach failures instead of a blank panel - #5427

Open
Glucksberg wants to merge 3 commits into
block:mainfrom
Glucksberg:fix/term-attach-failure-visible
Open

fix(desktop): surface Buzz Term attach failures instead of a blank panel#5427
Glucksberg wants to merge 3 commits into
block:mainfrom
Glucksberg:fix/term-attach-failure-visible

Conversation

@Glucksberg

Copy link
Copy Markdown

Summary

When the Term panel fails to attach, it renders nothing — a blank body with a + button that does nothing. TerminalBootstrap.fail() removes the session, sets available = false, and reports the error to console.error. In a production build there is no devtools to read that, and on Windows there is no log file either, so the error the backend produced is simply discarded on the way to the user.

That is the surface #4930 was reported through: the reporter saw a permanently blank Term panel and had nothing to attach to the issue except a Windows Event Log entry. The backend had a precise, actionable error the whole time — CreateProcessW "cmd.exe" in cwd None failed … (os error 2) — and the UI threw it away.

This renders that error in the viewport instead, with a Retry action that clears it and re-runs the auto-create path.

Before / after

Screenshots in the first comment. Both are the same element (.buzz-terminal-substrate) at the same viewport, so they're directly comparable.

Why there is no notice for "no channel selected"

An earlier version of this change also rendered "Select a channel to open a terminal." when the panel had no channel context. That state is not reachable, and shipping the notice would have been a small regression:

  • TerminalBootstrap.tsx — the Cmd/Ctrl+J toggle returns early when !context, so the panel cannot be opened without a channel.
  • An effect closes the panel when context goes away while it is open.

So the only way to render that notice is the single frame between navigating away from a channel and the effect running. That's a flash during navigation, not a state a user can be in. The existing test a non-channel route closes the panel and ignores the terminal shortcut already asserts this behaviour. The notice is now scoped to the one case that genuinely occurs: !available.

Relationship to #5425

Related, not a duplicate, and they fix different things.

Neither subsumes the other. With #5425 merged, a Windows user shouldn't reach the failure path by that route — but any future attach failure, on any platform, is silent again without this change. They can merge in either order; they touch no common files.

Related issue

Related to #4930 — this addresses the "Term panel renders permanently blank" symptom, which #5425 explicitly leaves out of scope. Deliberately not marked Fixes, since the root cause of that issue is the backend spawn failure, not this rendering gap.

Searched for duplicates: no other open PR touches desktop/src/features/terminal.

The issue's remaining item — "the desktop currently writes no log files on Windows" — is not addressed here.

Testing

  • Unit (TerminalBootstrap.test.mjs, 10/10): the notice renders with the backend's own error text, and Retry re-attaches after a failure. Full desktop JS suite: 4536/4536.
  • E2E screenshot spec (term-empty-states-screenshots.spec.ts, registered in the smoke project): drives the real attach-failure path end to end. The mock bridge doesn't implement terminal_attach, so the panel takes the genuine failure route rather than a stubbed one — the notice, its text, and the Retry button are all asserted before the capture.
  • pnpm check (biome, file sizes, px-text, pubkey truncation) and pnpm typecheck clean.

One note on reading the screenshot: the error string in it is the mock bridge's (Unsupported mocked Tauri command: terminal_attach), because that is what fails in an e2e build. On Windows the same slot carries the real CreateProcessW … error. The point of the shot is that whatever the backend said now reaches the user.

An attach failure removed the tab and set available=false with only a
console.error — unreachable in a production build, which has no
devtools and, on Windows, no log file. The user got a bare gray panel
with a dead + button and nothing to report (block#4930).

Render the failure in the viewport instead: 'Terminal unavailable:
<error>' with a Retry action, carrying the backend's own message
rather than a generic string. On Windows before block#5425 that reads
'CreateProcessW "cmd.exe" in cwd None failed ... (os error 2)' — the
error the panel already had and was throwing away. Retry clears it and
re-enables the auto-create path.

No notice for a missing channel context: the Cmd/Ctrl+J toggle refuses
to open the panel without one, and an effect closes the panel if the
channel goes away, so such a notice could only flash during navigation.

Covered by TerminalBootstrap unit tests (notice rendering, and retry
re-attaching after a failed attach) and a Playwright screenshot spec
that drives the real attach-failure path end to end via the mock
bridge, which does not implement terminal_attach.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: Glucksberg <glucksberg89@gmail.com>
@Glucksberg

Copy link
Copy Markdown
Author

Before — the silent panel

Attach fails, the session is removed, available goes false, and the viewport renders nothing. The + button is still there and still does nothing. This is what #4930 was reported through.

00-before

After — the failure is the UI

The backend's own error text, plus a Retry that clears it and re-runs the auto-create path.

01-term-attach-error

The error string here is the e2e mock bridge's (Unsupported mocked Tauri command: terminal_attach) — that is the real thing that fails in an e2e build, so the panel takes the genuine failure route rather than a stubbed one. On Windows the same slot carries CreateProcessW "cmd.exe" in cwd None failed … (os error 2).

Both images are .buzz-terminal-substrate captured at the same viewport, so they frame the identical element.

Signed-off-by: Glucksberg <glucksberg89@gmail.com>
@Glucksberg
Glucksberg marked this pull request as ready for review August 9, 2026 23:10
@Glucksberg
Glucksberg requested a review from a team as a code owner August 9, 2026 23:10

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a649d72e26

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +298 to +300
if (attachRetryRequestedRef.current) {
attachRetryRequestedRef.current = false;
createSession();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Retry the attachment in its original channel

When an attachment fails in channel B, failedAttachRef records only a global boolean. If the user navigates to channel A, which already has a healthy terminal, before clicking Retry, this effect calls createSession() with contextRef.current for A, spawning an unwanted extra shell there while the failed B attachment remains unretried until the user returns to B. Associate the retry with the failed channel/context, or only force creation when the current channel is the one whose attachment failed.

Useful? React with 👍 / 👎.

Signed-off-by: Glucksberg <glucksberg89@gmail.com>
@Glucksberg
Glucksberg force-pushed the fix/term-attach-failure-visible branch from f275713 to 72805dd Compare August 11, 2026 02:10
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