vitest-dev / vitest-dev/vitest

merge-reports + coverage.provider='v8' crashes in CI after upgrading to Vitest 4.1.2 / Vite 8.0.3, while istanbul passes

Open
#10,032 2 comments 3 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

pending triage
Dominant language
TypeScript
Stars
17.1k
Forks
2k
Avg merge
1d 22h
Merged PRs (30d)
94

Description

Summary

After upgrading to vitest@4.1.2 and vite@8.0.3, our CI merge report step crashes:

  • vitest run --merge-reports=.vitest-reports
  • coverage.provider = 'v8'
    The failure is a native crash (malloc / SIGSEGV / abort-style failure depending on the run), not a normal JS exception.
    If I switch coverage to istanbul provider then the merge job passes.
    This only happens in CI. Local runs use a different command path, so I do not yet have a local repro.

Affected setup

The failure only happens on one project in our monorepo, which is also the largest one and includes many stories.

 Test Files  478 passed (478)
 Tests  2880 passed (2880)

It uses Storybook browser testing through @storybook/addon-vitest/vitest-plugin and browser-enabled Vitest projects.


Expected behavior
vitest run --merge-reports=.vitest-reports should merge the blob reports and produce coverage output successfully.


Actual behavior
With coverage.provider = 'v8', the merge step crashes natively in CI.
There is no useful JS exception for the failing run. Depending on the run, I see native failures like:

  • malloc-related abort
  • segmentation fault / SIGSEGV

Important observations

  1. coverage.processingConcurrency=1 does not fix it
  2. Switching to the istanbul coverage provider makes the job pass
  3. With istanbul, Vite logs many stale/closed server errors
    Even though the job passes with istanbul, I see many stack traces like:
    Error: The server is being restarted or closed. Request is outdated
    at throwClosedServerError (file:///home/workflows/workspace/node_modules/vite/dist/node/chunks/node.js:29805:30)
    at EnvironmentPluginContainer.resolveId (file:///home/workflows/workspace/node_modules/vite/dist/node/chunks/node.js:29937:65)
    at resolveId (file:///home/workflows/workspace/node_modules/vite/dist/node/chunks/node.js:30638:38)
    at resolve (file:///home/workflows/workspace/node_modules/vite/dist/node/chunks/node.js:30650:22)
    at PluginContextImpl.resolveId (file:///home/workflows/workspace/node_modules/vite/dist/node/chunks/node.js:30797:28)
    at plugin (file:///home/workflows/workspace/node_modules/rolldown/dist/shared/bindingify-input-options-e7ze4hPR.mjs:1036:30)
    at plugin. (file:///home/workflows/workspace/node_modules/rolldown/dist/shared/bindingify-input-options-e7ze4hPR.mjs:1593:18)

Why I’m filing here first
From debugging the Vitest internals, merge-reports is not a pure offline merge:

  • it boots Vitest + Vite
  • loads Vite plugins/config
  • restores module graphs from blobs
  • initializes browser projects if present
  • then merges/generates coverage
    And the strongest signal I currently have is:
  • v8 crashes
  • istanbul passes
    So this looks most likely to be in Vitest’s merge-reports + coverage-v8 path, possibly with Vite 8 / Rolldown involved.

Thanks a lot for your help.

Reproduction

Coverage config is roughly:

coverage: {
  provider: 'v8',
  include: ['src/**/*.{js,jsx,ts,tsx}'],
  exclude: [
    'coverage/**',
    'dist/**',
    '**/node_modules/**',
    '**/*.d.ts',
    '**/virtual:*',
    'cypress/**',
    'test?(s)/**',
    'test?(-*).?(c|m)[jt]s?(x)',
    '**/*{.,-}{test,spec,bench,benchmark}?(-d).?(c|m)[jt]s?(x)',
    '**/__tests__/**',
    '**/{code-pushup,postcss,tailwind,karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build,eslint,prettier,playwright,orval}.config.*',
    '**/vitest.{workspace,projects}.[jt]s?(on)',
    '**/.{eslint,mocha,prettier}rc.{?(c|m)js,yml}',
    '.storybook/**',
    'mocks/**',
    'e2e/**',
    'src/generated/**'
  ],
}

How CI runs
Shards (3) produce blob reports, then a separate merge step runs:
vitest run --shard=1/3 --reporter=blob --reporter=default \ --coverage.reportsDirectory=./.vitest-coverage/shard-1 \ --outputFile.blob=.vitest-reports/blob-1.json
Then later:
vitest run --merge-reports=.vitest-reports
The shard runs pass.
The crash happens only during the merge step.

System Info
Binaries:
    Node: 24.11.1 
    Yarn: 4.3.1 
  npmPackages:
    @vitejs/plugin-basic-ssl: 2.3.0 => 2.3.0
    @vitejs/plugin-react: 6.0.1 => 6.0.1
    @vitejs/plugin-react-swc: 4.3.0 => 4.3.0
    @vitest/browser: 4.1.2 => 4.1.2
    @vitest/browser-playwright: 4.1.2 => 4.1.2
    @vitest/coverage-istanbul: 4.1.2 => 4.1.2
    @vitest/coverage-v8: 4.1.2 => 4.1.2
    @vitest/eslint-plugin: 1.6.13 => 1.6.13
    @vitest/ui: 4.1.2 => 4.1.2
    playwright: 1.55.1 => 1.55.1
    vite: 8.0.3 => 8.0.3
    vitest: 4.1.2 => 4.1.2
    vitest-mock-extended: 3.1.0 => 3.1.0
Used Package Manager

yarn

Validations

Contributor guide

Open the contributing guide

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.

Research direction

Start with the CI shard commands and vitest run --merge-reports=.vitest-reports, using the shown coverage.provider = 'v8' configuration. Compare the merge path with Istanbul and isolate the interaction among browser-enabled projects, Storybook's Vitest plugin, Vite 8, and Rolldown. Done means the V8 merge completes without a native crash and produces coverage output.

Written by the indexing model from the issue text.

Assessment

Tech stack
node.js, playwright, typescript, vite
Domain
build-system, ci-cd, testing-qa
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.