Skip to content

fix(coverage): skip non-file URLs when converting v8 coverage - #11074

Open
MFA-G wants to merge 1 commit into
vitest-dev:mainfrom
MFA-G:fix/coverage-v8-non-file-urls
Open

fix(coverage): skip non-file URLs when converting v8 coverage#11074
MFA-G wants to merge 1 commit into
vitest-dev:mainfrom
MFA-G:fix/coverage-v8-non-file-urls

Conversation

@MFA-G

@MFA-G MFA-G commented Aug 27, 2026

Copy link
Copy Markdown

Description

Fixes #11036.

V8CoverageProvider.convertCoverage calls fileURLToPath(result.url) unconditionally:

if (this.isIncluded(fileURLToPath(result.url))) {

If V8 reports a script whose URL is not a file: URL, fileURLToPath throws TypeError: The URL must be of scheme file (ERR_INVALID_URL_SCHEME) and the entire coverage run aborts — not just the offending entry. Real-world sources of such URLs:

  • about:/React/Server/... injected by vitest-plugin-rsc
  • data: inline modules
  • blob: worker scripts

filterResult in packages/coverage-v8/src/index.ts already drops non-file:// URLs at the takeCoverage stage, so the primary path is protected. But coverage entries that never pass through filterResult still reach convertCoverage: merged blob reports (--merge-reports), externally written coverage JSON, and subprocess writers. Those still crash today.

Change

Skip non-file: entries in convertCoverage (with a debug line) instead of letting fileURLToPath throw, so the remaining file-backed scripts are still converted and reported.

// V8 can report scripts that are not backed by a file, e.g. "about:", "data:"
// or "blob:" URLs coming from virtual modules. `fileURLToPath` throws on those.
if (!result.url.startsWith(FILE_PROTOCOL)) {
  debug('Skipping non-file URL %s', result.url)
  continue
}

The check runs after the browser-mode URL normalization block just above it, so browser /@fs and root-relative URLs — which are rewritten to file:// there — are unaffected.

Test

test/coverage-test/test/non-file-urls.unit.test.ts drives convertCoverage with a mixed batch: one non-file entry (parameterized over about:, data: and blob:) plus one real file-backed script, and asserts the file-backed script still lands in the coverage map.

Verified it is a real regression test — on main without the provider change it fails with exactly the reported error:

Serialized Error: { code: 'ERR_INVALID_URL_SCHEME' }
 Test Files  1 failed (1)
      Tests  3 failed (3)

and passes with it:

 ✓ |unit| test/non-file-urls.unit.test.ts > non-file url about:/React/Server/some-virtual-module does not crash coverage conversion
 ✓ |unit| test/non-file-urls.unit.test.ts > non-file url data:text/javascript,export const a = 1 does not crash coverage conversion
 ✓ |unit| test/non-file-urls.unit.test.ts > non-file url blob:nodedata:0ac1a2e2-... does not crash coverage conversion
 Test Files  1 passed (1)
      Tests  3 passed (3)

Validation

  • pnpm build — ok
  • vitest run --project unit --project v8 in test/coverage-test: 156 passed, 1 skipped, 1 failure in test/on-failure.test.ts (inline snapshot of the coverage summary text). That failure reproduces on an unmodified checkout of main as well, so it is pre-existing and unrelated to this change.
  • eslint clean on both touched files.

`convertCoverage` calls `fileURLToPath(result.url)` unconditionally, so any
script V8 reports with a non-`file:` URL ("about:" virtual modules from
vitest-plugin-rsc, "data:" inline modules, "blob:" workers) throws
`ERR_INVALID_URL_SCHEME` and aborts the whole coverage run.

`filterResult` in `packages/coverage-v8/src/index.ts` already drops these at
the `takeCoverage` stage, but coverage entries that never go through it —
merged blob reports, externally written coverage JSON, subprocess writers —
still reach `convertCoverage` and crash.

Skip those entries instead, so the remaining file-backed scripts are still
reported.

Closes vitest-dev#11036
@github-actions github-actions Bot added the maybe automated User is likely an AI agent, or the content was generated by an AI assistant without user control label Aug 27, 2026
@github-actions

Copy link
Copy Markdown

Hello @MFA-G. Your PR has been labeled maybe automated because it appears to have been fully generated by AI with no human involvement.

To keep your PR open, please follow these steps:

  • Confirm that you are a real human. If you are an automated agent, disclose that
  • Make sure you've read, reviewed and stand behind its content
  • Make sure you've read the full issue along with all of its comments, as well as any linked issues and their comments
  • Make sure it follows our contribution guidelines and uses the correct GitHub template
  • Disclose any AI tools you used (e.g. Claude, Copilot, Codex)

Please, do not generate or format the response with AI. If you do not speak English, reply in your native language or use translation software like Google Translate or Deepl. If the response is generated, the PR will be closed automatically.

These measures help us reduce maintenance burden and keep the team's work efficient. See our AI contributions policy for more context.

@netlify

netlify Bot commented Aug 27, 2026

Copy link
Copy Markdown

Deploy Preview for vitest-dev ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit f686cf6
🔍 Latest deploy log https://app.netlify.com/projects/vitest-dev/deploys/6a9039f1184e2f00085ce6bb
😎 Deploy Preview https://deploy-preview-11074--vitest-dev.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

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

Labels

maybe automated User is likely an AI agent, or the content was generated by an AI assistant without user control

Projects

None yet

Development

Successfully merging this pull request may close these issues.

@vitest/coverage-v8: crashes on non-file: URLs (e.g. RSC virtual modules)

1 participant