Skip to content

Closing rpc while "onAfterSuiteRun" was pending when another RPC call fails during teardown #11925

Open

Description

@TrevorBurnham

Describe the bug

With coverage enabled, a run where every test passes can sometimes fail with:

⎯⎯⎯⎯ Unhandled Rejection ⎯⎯⎯⎯⎯
EnvironmentTeardownError: [vitest-worker]: Closing rpc while "onAfterSuiteRun" was pending
This error originated in "test/sum.test.js" test file. It doesn't mean the error was thrown inside the file itself, but while it was running.

 Test Files  1 passed (1)
      Tests  1 passed (1)
     Errors  1 error

This seems to be because rpcDone() in packages/vitest/src/runtime/rpc.ts uses Promise.all. When the worker finishes, it waits on rpcDone(), then rejects whatever is still pending. If any in-flight call rejects, Promise.all settles right away, and the cleanup then rejects onAfterSuiteRun. Nothing handles that rejection, because onAfterSuiteRun is sent without being awaited (runtime/runners/index.ts).

Switching rpcDone() from Promise.all to Promise.allSettled should fix it. Ignoring EnvironmentTeardownError on the onAfterSuiteRun call, as console.ts does for onUserConsoleLog, would also work.

Reproduction

https://github.com/TrevorBurnham/vitest-onAfterSuiteRun-repro

Pull that repo down and run npm install && npm test. On my Mac, it fails in almost every run with coverage on, and passes with coverage off.

Here's how it makes the non-deterministic bug reproduce almost all the time:

  • starts a caught, unawaited import that a plugin fails after 500 ms
  • blocks the main process for 1 s from a reporter once the file finishes, standing in for a busy CI machine
  • loads a large generated module, so collecting coverage in the worker takes longer than the 100 ms task-update throttle

The README walks through the order of events.

System Info

System:
  OS: macOS 27.2
  CPU: (15) arm64 Apple M5 Pro
Binaries:
  Node: 24.22.2
  npm: 11.19.1
npmPackages:
  @vitest/coverage-v8: 5.1.0 => 5.1.0
  vitest: 5.1.0 => 5.1.0

Used Package Manager

npm

Activity

  1. abhinav-phi commented on Nov 11, 2026

    @abhinav-phi
    Contributor

    Thanks for the diagnosis — it matched what I found while working on this.

    The change is ready on fix/11925-rpc-allsettled:

    • rpcDone() waits for every in-flight call to settle with Promise.allSettled, and re-throws the first rejection once they have all settled.
    • The fire-and-forget onAfterSuiteRun call ignores EnvironmentTeardownError, the same way console.ts already does for onUserConsoleLog.

    I ran your reproduction against a local build of that branch. Without the change the run ends with Errors 1 error; with it the run exits 0 and reports no errors. There is also a unit test for rpcDone that fails without the change.

    The pull request was closed automatically by the repository's account scan, so there is nothing open for review at the moment, and the branch sits on my fork. The fix is small enough to re-implement, so please take it if you would rather, and I am happy to open a fresh pull request if that is preferred.

    Written with AI assistance (opencode); the change and its tests were verified against your reproduction locally.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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