Skip to content

🐛 BUG: vitest-plugin coverage shim doesn't handle __vitest_stopV8Coverage under vitest 5 #16238

Closed

Description

@colby-makowsky

What versions & operating system are you using?

System:
  OS: macOS 27.0.1
  CPU: (10) arm64 Apple M4
Binaries:
  Node: 26.8.2
  npm: 11.19.1
npmPackages:
  @cloudflare/vitest-plugin: 1.4.0
  @vitest/coverage-v8: 5.0.4
  vitest: 5.0.4
  wrangler: 4.149.0

Please provide a link to a minimal reproduction

Five small files, inline:

package.json

{
  "type": "module",
  "devDependencies": {
    "@cloudflare/vitest-plugin": "1.4.0",
    "@vitest/coverage-v8": "5.0.4",
    "vitest": "5.0.4",
    "wrangler": "^4.135.0"
  }
}

wrangler.jsonc

{ "name": "repro", "main": "src/index.ts", "compatibility_date": "2026-10-01", "compatibility_flags": ["nodejs_compat"] }

src/index.ts

export default {
  fetch() {
    return new Response("ok");
  },
};

test/index.test.ts

import { SELF } from "cloudflare:test";
import { expect, it } from "vitest";

it("responds", async () => {
  const res = await SELF.fetch("https://example.com");
  expect(await res.text()).toBe("ok");
});

vitest.config.ts (fsModuleCache is off only to avoid a separate vitest 5 bug; see #16237)

import { cloudflareTest } from "@cloudflare/vitest-plugin";
import { defineConfig } from "vitest/config";

export default defineConfig({
  plugins: [cloudflareTest({ wrangler: { configPath: "./wrangler.jsonc" } })],
  test: { fsModuleCache: false, coverage: { provider: "v8" } },
});

Then npx vitest run --coverage.

Describe the Bug

Under vitest 5, @vitest/coverage-v8 drives coverage in the isolate through __vitest_browser_runner__.commands.triggerCommand. Its stopCoverage sends __vitest_stopV8Coverage at the end of every test file (unless isolate: false). The shim the plugin installs in the runner Durable Object handles __vitest_startV8Coverage, __vitest_takeV8Coverage and __vitest_writeCoverageFile. It has no branch for __vitest_stopV8Coverage, so the command reaches assert.strictEqual(command, "__vitest_writeCoverageFile") and throws. This is still the case on main in packages/vitest-plugin/src/worker/index.ts.

Expected: coverage runs cleanly and exits 0.

Actual: the test passes, but Vitest reports one unhandled error per test file and exits 1. The coverage report itself is unaffected: the numbers are identical with the fix below. The inspector session isn't closed at the end of the file; the next __vitest_startV8Coverage closes it.

Suggested fix (we're carrying it as a postinstall patch against 1.4.0's built output, and the error is gone):

if (command === "__vitest_stopV8Coverage") {
  await this.stopV8CoverageSession();
  return "";
}

placed before the __vitest_writeCoverageFile assertion.

Please provide any relevant error logs

AssertionError: Values are not strictly equal:

-   __vitest_stopV8Coverage
+   __vitest_writeCoverageFile

 ❯ assert.strictEqual node-internal:internal_assert:196:11
 ❯ Object.triggerCommand index.mjs:863:11
 ❯ triggerCommand node_modules/@vitest/coverage-v8/dist/browser.js:7:55
 ❯ Object.stopCoverage node_modules/@vitest/coverage-v8/dist/browser.js:24:9
 ❯ stopCoverageInsideWorker node_modules/vitest/dist/chunks/coverage.-bm5IxnW.js:22:58

Activity

  1. workers-devprod commented on Oct 13, 2026

    @workers-devprod
    Contributor

    Automated triage

    Issue assessment

    • Actionability: ✅ Actionable.
    • Type: Bug.
    • Reproduction: Automatic attempt requested.
    • Labels:
      • bug (high)
      • package:vitest (high)
    Actionability and missing information

    Under vitest 5, the vitest plugin's runner coverage shim lacks a __vitest_stopV8Coverage branch, so the writeCoverageFile assertion throws an unhandled error per test file and vitest exits 1; the report includes versions, minimal repro, expected and actual behavior, and error output.

    Reproduction reason: The report describes a defect that plausibly persists in the current plugin and supplies a complete minimal reproduction: versions, config files, command, expected and actual behavior, and error output.

    Reproduction

    • Result: ✅ Reproduced.
    • Summary: Reproduced with vitest-plugin 1.4.0 and vitest 5.0.4: vitest run --coverage exits 1; the test passes and the v8 report emits, but Vitest reports 1 unhandled AssertionError (__vitest_stopV8Coverage vs __vitest_writeCoverageFile) from the plugin shim's triggerCommand index.mjs:863:11, as reported.
    Evidence and attempted steps

    Steps attempted:

    1. Built the issue's five-file fixture (package.json, wrangler.jsonc, src/index.ts, test/index.test.ts, vitest.config.ts with v8 coverage); pinned vitest-plugin 1.4.0, vitest 5.0.4, coverage-v8 5.0.4, wrangler 4.149.0; pnpm 10.34.7 on Node v22.23.2.
      • Command: pnpm install --no-frozen-lockfile # in /workspace/repro-work/project
    2. Baseline sanity check without coverage to distinguish a broken setup from the reported bug.
      • Command: ./node_modules/.bin/vitest run # exit=0, 1 test passed, no errors
    3. Reproduction run with v8 coverage, exactly as in the issue.
      • Command: ./node_modules/.bin/vitest run --coverage # exit=1, 'Vitest caught 1 unhandled error'
    4. Cross-checked the installed plugin's built worker shim: only line 863 'assert.strictEqual(command, "__vitest_writeCoverageFile")' matches; no __vitest_stopV8Coverage handler exists, matching the issue's claim.
      • Command: grep -n '__vitest_stopV8Coverage|__vitest_writeCoverageFile' node_modules/vitest-plugin/dist/worker/index.mjs

    Expected behavior: Coverage runs cleanly and exits 0 (per the issue): vitest run --coverage completes with no unhandled errors, the test passes, and the v8 coverage report is produced.

    Observed behavior: vitest run --coverage exits 1. The test passes (1/1) and the v8 coverage report is still emitted (index.ts 100%), but Vitest reports 'Vitest caught 1 unhandled error during the test run': AssertionError 'Values are not strictly equal: - __vitest_stopV8Coverage + __vitest_writeCoverageFile' thrown at Object.triggerCommand index.mjs:863:11 (the plugin's worker shim), reached via the coverage-v8 package's stopCoverage and vitest's stopCoverageInsideWorker; the stack frame matches the issue's log exactly. A baseline run without --coverage exits 0 with no errors.

    Artifact: Download reproduction archive (Cloudflare Access required).

    Treat archive contents as untrusted. Inspect them before running anything.


    This summary was generated by an LLM and may contain errors. Please verify its findings.

    Triage bot commands and options

    Repository collaborators with write or admin access can trigger actions by commenting on this issue:

    • @workers-devprod reproduce: Attempt to reproduce the issue using its description and recent comments.
  2. dario-piotrowicz commented on Oct 28, 2026

    @dario-piotrowicz
    Member

    Thanks for the issue @colby-makowsky 🙏

    I'm closing it since I believe that this has already been addressed by #16248

    If you disagree please feel free to reopen this or create a new issue

  3. moved this from Untriaged to Done in workers-sdkon Oct 28, 2026
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

    bugpackage:vitestRelating to the Workers Vitest integration

    Type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions