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

Closed Beginner friendly
#16,238 1 comment 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
83/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
typescript
Domain
devtools, testing

Research direction

Start in packages/vitest-plugin/src/worker/index.ts and trace how the runner Durable Object handles coverage commands. Compare the existing start and take handlers with the Vitest 5 stop command described in the report. Done means npx vitest run --coverage exits 0 for the five-file reproduction without unhandled errors.

Written by the indexing model from the issue text.

Description

bug package:vitest
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 https://github.com/cloudflare/workers-sdk/issues/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
Dominant language
TypeScript
Stars
4.7k
Forks
1.6k
Avg merge
1d 12h
Merged PRs (30d)
226

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from cloudflare/workers-sdk

All issues in cloudflare/workers-sdk

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.