{"id":"ad60f6385d09b711","repo":"vitest-dev/vitest","slug":"something-removed-the-coverage-directory-covera-ad60f6","errorCode":null,"errorMessage":"Something removed the coverage directory \"${coverageFilesDirectory}\" Vitest created earlier. Make sure you are not running multiple Vitests with the same \"coverage.reportsDirectory\" at the same time.","messagePattern":"Something removed the coverage directory \"(.+?)\" Vitest created earlier\\. Make sure you are not running multiple Vitests with the same \"coverage\\.reportsDirectory\" at the same time\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coverage-v8/src/commands.ts","lineNumber":54,"sourceCode":"\n  const provider = context.project.vitest.coverageProvider as V8CoverageProvider\n\n  return await writeCoverageFile(provider.coverageFilesDirectory, { result })\n}\n\nexport async function writeCoverageFile(coverageFilesDirectory: string, coverage: unknown): Promise<string> {\n  // Write results on file system directly and transfer only the filename over RPC\n  const filename = resolve(\n    coverageFilesDirectory,\n    `coverage-${randomUUID()}.json`,\n  )\n\n  try {\n    await writeFile(filename, JSON.stringify(coverage), 'utf-8')\n  }\n  catch (error) {\n    if (!existsSync(coverageFilesDirectory)) {\n      throw new Error(\n        `Something removed the coverage directory \"${coverageFilesDirectory}\" Vitest created earlier. Make sure you are not running multiple Vitests with the same \"coverage.reportsDirectory\" at the same time.`,\n        { cause: error },\n      )\n    }\n\n    throw error\n  }\n\n  return filename\n}\n\nfunction filterResult(url: string, origin: string, pageUrl: string): boolean {\n  if (!url.startsWith(origin)) {\n    return false\n  }\n\n  if (url.includes('/node_modules/')) {\n    return false","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/vitest-dev/vitest/blob/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/coverage-v8/src/commands.ts#L36-L72","documentation":"Identical guard to the Istanbul one but in the V8 coverage provider's writeCoverageFile. After CDP coverage is collected and filtered, it is written to coverageFilesDirectory; if the write fails and that directory is gone, the provider blames a concurrent Vitest that deleted it.","triggerScenarios":"takeV8Coverage (browser CDP) calls writeCoverageFile; the JSON write throws and existsSync(coverageFilesDirectory) returns false, producing this error with the underlying FS error as cause.","commonSituations":"Parallel CI jobs with the same coverage.reportsDirectory; coverage directory on a tmpfs that gets cleaned; a post-run hook deleting coverage/ before the browser provider flushes its file.","solutions":["Set a unique coverage.reportsDirectory per concurrent Vitest process.","Serialize coverage runs in CI.","Ensure nothing cleans the reports directory while a run is in progress."],"exampleFix":"// before\n// vitest --coverage --coverage.provider=v8  (run twice in parallel)\n// after\n// run 1: --coverage.reportsDirectory=coverage/v8-a\n// run 2: --coverage.reportsDirectory=coverage/v8-b","handlingStrategy":"validation","validationCode":"import { existsSync, mkdirSync } from 'node:fs'\nif (!existsSync(coverageFilesDirectory)) {\n  mkdirSync(coverageFilesDirectory, { recursive: true })\n}","typeGuard":null,"tryCatchPattern":"try {\n  await writeCoverageFile(dir, { result })\n} catch (e) {\n  if (/removed the coverage directory/i.test(String((e as Error).message))) {\n    mkdirSync(dir, { recursive: true })\n    return writeCoverageFile(dir, { result })\n  }\n  throw e\n}","preventionTips":["Assign unique reportsDirectory values to parallel v8-coverage runs.","Avoid shared tmpfs that gets reaped during the run.","Keep post-run cleanup hooks out of the active run window."],"tags":["coverage","v8","filesystem","concurrency"],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}