← Dev log
Ferry·frontend·2026-09-15

A VS Code panel that was empty, and a test that passed anyway

A useRef initializer runs on every render, not just the first, so each re-render called acquireVsCodeApi() again — VS Code allows it once per webview, and the panel rendered empty.

The safety net had a hole

The test, the audit log, the scanner, the CI run — covering less than I assumed it did.

First real install of the packaged .vsix: "Ferry: Open Panel" and "Pair a Device" opened an empty webview.

The cause was useRef(client ?? new FerryClient()) — a useRef initializer is evaluated on every render, not just the first, so each re-render constructed a fresh FerryClient → VsCodeTransport → called acquireVsCodeApi() again. VS Code only allows that call once per webview; the second call throws, and React unmounted the whole tree. It never showed up in the browser build, because there the same mistake just leaked a spare WebSocketTransport per render instead of crashing.

The existing e2e test was green the entire time this bug existed, because it only asserted that a tab named "Ferry" existed — not that anything rendered inside it.

Fixed the bug (a lazy useRef init, plus a module-level cache so acquireVsCodeApi() can never be called twice again) and fixed the test to wait for the webview's own {kind:"start"} message before passing, so "opened but never mounted" is now a hard failure. Verified failing before the fix and passing after, on a real VS Code install.

The gap between "the container is there" and "the thing inside works" is exactly where a real user's experience and a passing test suite can diverge for a long time without anyone noticing. Assert on a signal the application itself emits when it's actually ready, not on a signal that the host merely opened a slot for it.