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.subdirView on GitHub (pinned to d568f8ce37)
Solutions
- Point reportsDirectory at a dedicated subfolder: `reportsDirectory: './coverage'` (the default).
- If you need a custom location, ensure it is strictly inside the project, not the root itself.
- 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
- Keep the default './coverage' or a named subfolder.
- Never set reportsDirectory to '.' or '/'.
- Resolve absolute paths and compare against root before applying.
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
- Access denied to "${path}". See Vite config documentation fo
- Cannot modify file "${path}". File writing is disabled becau
- Something removed the coverage directory "${coverageFilesDir
- Something removed the coverage directory "${coverageFilesDir
- "Istanbul" coverage provider is not compatible with "experim
AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03).
Data as JSON: /data/errors/9aea5b61e49688ab.json.
Report an issue: GitHub.