Repository navigation
fix(dash0): live-socket CONNECTING crash + route-level error boundaries - #108
Merged
Merged
Conversation
… boundaries The live-updates WebSocket client exposed its send() surface as soon as the socket was created (readyState CONNECTING). A component mounting during that dial window - or during a reconnect attempt - made the subscription registry send a subscribe frame immediately, and the browser threw "Failed to execute 'send' on 'WebSocket': Still in CONNECTING state" inside a React effect, blanking the whole app. The socket is now handed to send() only once the server acks auth (hello), matching the server handshake which requires auth as the first frame. Frames sent before that are dropped, which is safe: onOpen replays every active scope after each (re)connect, and an unsubscribe for a never-subscribed scope needs no undoing. The test FakeSocket now mimics the browser (throws on send while CONNECTING) and three new tests pin the pre-open, pre-hello, and mid-reconnect windows. On the UX side, route errors no longer fall through to TanStack Router's bare default screen: a shared ErrorFallbackCard (friendly copy, collapsible technical details, Try again + Reload actions) is wired as the router's defaultErrorComponent, so a crash renders inside the layout with the sidebar still usable, and "Try again" re-runs loaders after resetting the boundary. The root ErrorBoundary reuses the same card, and the pattern is catalogued in the design reference. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
fclairamb
enabled auto-merge (squash)
July 6, 2026 17:57
Merged
fclairamb
added a commit
that referenced
this pull request
Jul 8, 2026
🤖 I have created a release *beep* *boop* --- ## [0.2.1](v0.2.0...v0.2.1) (2026-07-08) ### Features * **dash0:** one-click MCP connector setup — AI assistants page with a URL-only OAuth flow, per-client icons, shared copy/collapsible code primitives ([#111](#111)) ([d105be4](d105be4)) * **dash0:** Recent activity links directly to the originating incident/check and shows the channel name; incident lifecycle events enriched with check UID/name ([#111](#111)) ([d105be4](d105be4)) * **entitlements:** SaaS Free-plan defaults now match the billing Free plan (10 checks, 6/min, no SSO), with a backend-driven "Free"/"Team"/"Self-hosted" plan display identity ([#111](#111)) ([d105be4](d105be4)) * **devloop:** `make dev`/`make dev-test` supervise dash0 and status0 with size-rotated per-process logs instead of unbounded raw output ([#111](#111)) ([d105be4](d105be4)) ### Bug Fixes * **checks:** list endpoint no longer overfetches O(retention) raw rows per check for `lastResult` — one row per check via `DISTINCT ON` ([#111](#111)) ([d105be4](d105be4)) * **e2e:** dashboard E2E suite flaked on per-test login contention; authenticate once per Playwright worker instead of once per test ([#111](#111)) ([d105be4](d105be4)) * **db:** embedded-Postgres orphan sweep + watchdog reclaims leaked dev/test instances left behind by crashed processes ([#111](#111)) ([d105be4](d105be4)) * **realtime:** check-detail live subscription used the URL slug instead of the canonical uid, silently breaking live updates on slug-based check URLs ([#111](#111)) ([d105be4](d105be4)) * **e2e:** hardcoded `localhost:4000` in several spec files ignored `E2E_BASE_URL`, breaking test runs against non-default servers ([#111](#111)) ([d105be4](d105be4)) * **checkworker:** check results fell back to a null region for default-region checks instead of the executing worker's own region ([#111](#111)) ([d105be4](d105be4)) * **notifications:** a malformed notification UID errored on the Postgres `uuid` column cast instead of rendering the friendly not-found state ([#111](#111)) ([d105be4](d105be4)) * **dash0:** live-socket CONNECTING crash + route-level error boundaries ([#108](#108)) ([008c015](008c015)) * **deps:** update go dependencies (non-major) ([#109](#109)) ([ec616d4](ec616d4)) * **deps:** update module github.com/oapi-codegen/oapi-codegen/v2 to v2.7.2 ([#110](#110)) ([09d6ad0](09d6ad0)) * **deps:** update module github.com/ohler55/ojg to v1.28.2 ([#107](#107)) ([335615c](335615c)) * **deps:** update module github.com/wneessen/go-mail to v0.8.0 ([#103](#103)) ([aa533c1](aa533c1)) * Slack multi-org, region filtering, mail-checker hang fixes, live-status dot ([#100](#100)) ([35f3aa2](35f3aa2)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
This was referenced Sep 8, 2026
Closed
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Full-app crash:
Failed to execute 'send' on 'WebSocket': Still in CONNECTING state.The live-updates socket client (
web/dash0/src/lib/live-socket.ts) exposed itssend()surface at socket creation time. Any component mounting while the socket was dialing (first connect or any reconnect attempt) made the subscription registry send asubscribeframe into a CONNECTING socket, which throws — inside a React effect, unwinding the entire route tree to the router's bare default error screen.Fix
send()only gets the socket once the server acks auth (hello) — the server handshake requiresauthas the first frame anyway, so earlier frames were invalid regardless. Frames before that are dropped, which is safe:onOpenreplays every active scope after each (re)connect, and an unsubscribe for a never-subscribed scope needs no undoing server-side.FakeSocketnow mimics the browser (throws on send while CONNECTING; discards after close), plus three regression tests covering the pre-open, open-but-pre-hello, and mid-reconnect windows.Better error UX
ErrorFallbackCard(friendly copy, collapsible technical details, Try again + Reload page) inerror-boundary.tsx.defaultErrorComponent: a route error now renders inside the layout — sidebar and navigation stay usable — and "Try again" resets the boundary and re-runs loaders. Errors feed the existing bug-report ring buffer.ErrorBoundaryreuses the card; pattern added to the design reference (Feedback section).Testing
vitest run— 107/107 pass (incl. 3 new regression tests)tsc -bclean; eslint: no new errors (only the known pre-existingDate.now()debt in design-reference)🤖 Generated with Claude Code