Skip to content

Browser mode: run hangs forever when a tester page dies without closing its websocket (no run-level deadline on createTesters) #10791

Description

@joelfillmore

Describe the bug

In browser mode, if a tester page's JS context dies without closing its websocket, the whole run hangs forever with no output — testTimeout, retry, and reporters all go silent until something external kills the process (locally Ctrl-C, on CI timeout-minutes).

The hang is structural — there is no run-level deadline anywhere on the per-file execution path:

  • The node-side RPC to the orchestrator is created with timeout: -1 (@vitest/browser setupClient), so orchestrator.createTesters([file]) in the pool's runNextTest can wait forever. Pending calls are only rejected by the websocket close handler ("Browser connection was closed while running tests").
  • In the page, the orchestrator's sendEventToIframe({ event: 'execute' }) returns a promise that resolves only when the tester posts response:execute on the BroadcastChannel — no timeout, and only an iframeerror event can reject it.
  • testTimeout and retry are enforced inside the tester iframe's own JS, so once that context is gone they can never fire.

browser.connectTimeout only covers session creation; nothing covers "tester died mid-file with the socket still open."

Real triggers we hit (all funnel into the same unbounded wait):

Reproduction

Deterministic illustration of the missing deadline (any browser-mode project, playwright provider):

  1. vitest run a suite with enough files to take ~30s.
  2. Mid-run, freeze the browser: pkill -STOP -f headless_shell (the websocket stays open, so the close-handler rescue never fires).
  3. The run produces no further output and never times out — testTimeout cannot fire because it lives inside the frozen page.

The organic version (optimizer-reload trigger) is racy by nature: cold optimizer cache + a dep that misses the initial scan → mid-run re-optimize → full reload → hang. Observed repeatedly on a ~110-file / ~850-test storybook (@storybook/addon-vitest) suite.

Expected behavior

A tester that stops responding should fail that test file (and let the run continue or fail fast), not hang the run forever. Possible shapes: a configurable deadline around createTesters per file, or a heartbeat between orchestrator/tester and the node side that converts a dead-but-connected session into a file-level error.

Related: #9509 (load-time flakes), #10520 (hang at collection), #8447 / #7333 (unexpected reload warning), #9437 (disk accumulation — one of the triggers).

System Info

  • vitest / @vitest/browser / @vitest/browser-playwright 4.1.10 (also reproduced conceptually against current dist)
  • provider: playwright, chromium headless
  • observed on macOS 15 (arm64), ubuntu 24 (x64 GitHub runners, docker arm64)
  • node 24

Used Package Manager

pnpm

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions