vitest-dev/vitest · error · Error

You cannot set "coverage.reportsDirectory" as ${reportsDirec

Error message

You cannot set "coverage.reportsDirectory" as ${reportsDirectory}. Vitest needs to be able to remove this directory before test run

What it means

Vitest clears the coverage reports directory at the start of each run to avoid stale data mixing with new results. The guard at resolveConfig.ts:481 refuses to proceed when the resolved `coverage.reportsDirectory` equals the project root or the current working directory, because deleting either would wipe the whole project.

Source

Thrown at packages/vitest/src/node/config/resolveConfig.ts:485

        resolved.coverage.reporter.push(['text-summary', {}])
      }
    }
  }
  if (resolved.coverage.changed === undefined && resolved.changed !== undefined) {
    resolved.coverage.changed = resolved.changed
  }

  if (resolved.coverage.enabled && resolved.coverage.reportsDirectory) {
    const reportsDirectory = resolve(
      resolved.root,
      resolved.coverage.reportsDirectory,
    )

    if (
      reportsDirectory === resolved.root
      || reportsDirectory === process.cwd()
    ) {
      throw new Error(
        `You cannot set "coverage.reportsDirectory" as ${reportsDirectory}. Vitest needs to be able to remove this directory before test run`,
      )
    }

    if (resolved.coverage.htmlDir) {
      resolved.coverage.htmlDir = resolve(
        resolved.root,
        resolved.coverage.htmlDir,
      )
    }

    // infer default htmlDir based on builtin reporter's html output location
    if (!resolved.coverage.htmlDir) {
      const htmlReporter = resolved.coverage.reporter.find(([name]) => name === 'html' || name === 'html-spa')
      if (htmlReporter) {
        const [, options] = htmlReporter
        const subdir = options && typeof options === 'object' && 'subdir' in options && typeof options.subdir === 'string'
          ? options.subdir

View on GitHub (pinned to d568f8ce37)

Solutions

  1. Point reportsDirectory at a dedicated subfolder: `reportsDirectory: './coverage'` (the default).
  2. If you need a custom location, ensure it is strictly inside the project, not the root itself.
  3. Double-check absolute paths that they don't resolve to process.cwd().

Example fix

// before
export default defineConfig({ test: { coverage: { enabled: true, reportsDirectory: '.' } } })
// after
export default defineConfig({ test: { coverage: { enabled: true, reportsDirectory: './coverage' } } })
Defensive patterns

Strategy: validation

Validate before calling

import { resolve } from 'node:path'
function assertReportsDirectorySafe(reportsDirectory: string, root: string) {
  const resolved = resolve(root, reportsDirectory)
  if (resolved === root || resolved === process.cwd()) {
    throw new Error(`coverage.reportsDirectory (${resolved}) must not be the project root or cwd.`)
  }
}

Type guard

function isReportsDirectorySafe(reportsDirectory: string, root: string): boolean {
  const resolved = resolve(root, reportsDirectory)
  return resolved !== root && resolved !== process.cwd()
}

Prevention

When it happens

Trigger: Set `coverage: { reportsDirectory: '.' }`, `reportsDirectory: '/'`, or `reportsDirectory` resolving to `process.cwd()` or `resolved.root`.

Common situations: Setting reportsDirectory to '.' to put coverage next to the config; absolute path that happens to be the repo root; relative path that resolves up to root.

Related errors


AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03). Data as JSON: /data/errors/9aea5b61e49688ab.json. Report an issue: GitHub.