Skip to content

fix(browser): size the display on firstFrame, not when connect resolves - #1196

Merged
philmerrell merged 1 commit into
developfrom
fix/browser-live-view-display-layout-timing
Sep 19, 2026
Merged

philmerrell merged 1 commit into
developfrom
fix/browser-live-view-display-layout-timing

Conversation

@philmerrell

Copy link
Copy Markdown
Contributor

What

The viewer logged an unhandled rejection on every connect:

Uncaught (in promise) {code: 2, message: Display channel is not available.}

requestDisplayLayout was called from connect().then(), but the display channel is not up at that point. It returns a promise, so the try/catch around it never saw the failure — it escaped as an unhandled rejection. That is also why the comment claiming "Not fatal: the stream renders at whatever the server chose" was never actually exercised: the code path it described didn't run.

Moved into the firstFrame observer, which by definition fires once the display channel is live, and the returned promise is caught so a declined layout is a console note rather than an unhandled rejection.

Context

Found while establishing whether the live view is now streaming at all. It appears to be: after #1190, #1192 and #1194 the console shows Added connection 1 to connections, the display and input channels initialising, and no disconnect in 11 minutes. This rejection was the loudest remaining error and it turned out to be ours, and cosmetic.

Two things remain open and are NOT addressed here:

  • A spurious second authenticate per open. app-api is minting twice per viewer open (two POST …/browser/live-view per session), and the second mint drives a second auth attempt that fails with code 10 while the first succeeds. Each mint is a live signed credential, so this is worth fixing on its own merits.
  • Visual confirmation that pixels are actually rendering. The Browser pane is not compositing in this session, so I cannot screenshot it.

Tests

Asserts the layout is requested only after firstFrame, with the session's real viewport, and that a rejected request does not propagate.

Mutation-checked: restoring the .then() call fails the new assertion. Suite 878 pass, tsc --noEmit clean — tsc again caught typing jest's transpile-only run did not.

🤖 Generated with Claude Code

The viewer logged an unhandled rejection on every connect:

  Uncaught (in promise) {code: 2, message: Display channel is not available.}

`requestDisplayLayout` was called from `connect().then()`, but the display
channel is not up at that point. It returns a PROMISE, so the try/catch
around it never saw the failure — it escaped as an unhandled rejection,
which is also why the comment claiming "not fatal" was never actually
exercised.

Moved into the `firstFrame` observer, which by definition fires once the
display channel is live, and the returned promise is now caught so a
declined layout stays a console note rather than an unhandled rejection.
The stream remains usable at whatever size the server chose.

Mutation-checked: calling it from `.then()` again fails the new assertion.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@philmerrell
philmerrell merged commit 8d784c4 into develop Sep 19, 2026
6 checks passed
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