vitest-dev/vitest · error · Error

Access denied to "${path}". See Vite config documentation fo

Error message

Access denied to "${path}". See Vite config documentation for "server.fs": https://vitejs.dev/config/server-options.html#server-fs-strict.

What it means

Thrown by assertBrowserFileAccess() when Vite's isFileLoadingAllowed returns false for both the project Vite config and the main Vitest Vite config. This is Vitest delegating to Vite's server.fs.allow / server.fs.strict security boundary to prevent browser commands from reading files outside allowed roots.

Source

Thrown at packages/browser/src/node/utils.ts:106

    )
  }
  if (typeof options.provider.providerFactory !== 'function') {
    throw new TypeError(`The "${name}" browser provider does not provide a "providerFactory" function. Received ${typeof options.provider.providerFactory}.`)
  }
  return options.provider.providerFactory(project)
}

export function slash(path: string): string {
  return path.replace(/\\/g, '/').replace(/\/+/g, '/')
}

export function assertBrowserFileAccess(project: TestProject, path: string): void {
  const normalized = slash(path)
  if (
    !isFileLoadingAllowed(project.vite.config, normalized)
    && !isFileLoadingAllowed(project.vitest.vite.config, normalized)
  ) {
    throw new Error(
      `Access denied to "${path}". See Vite config documentation for "server.fs": https://vitejs.dev/config/server-options.html#server-fs-strict.`,
    )
  }
}

export function assertBrowserApiWrite(project: TestProject, path: string): void {
  if (!project.config.api.allowWrite || !project.vitest.config.api.allowWrite) {
    throw new Error(
      `Cannot modify file "${path}". File writing is disabled because the server is exposed to the internet, see https://vitest.dev/config/browser/api.`,
    )
  }
}

View on GitHub (pinned to d568f8ce37)

Solutions

  1. Add the directory to server.fs.allow in your Vite/Vitest config, e.g. server: { fs: { allow: ['/abs/path'] } }.
  2. Move fixture files inside the project root so they fall under the default allowed root.
  3. Disable server.fs.strict only if you understand the security implications.

Example fix

// before
export default defineConfig({
  test: {
    browser: { enabled: true },
    // readFile('/shared/fixtures/data.json') fails — outside root
  },
})
// after
export default defineConfig({
  server: { fs: { allow: ['/shared/fixtures'] } },
  test: { browser: { enabled: true } },
})
Defensive patterns

Strategy: validation

Validate before calling

import { isFileLoadingAllowed } from 'vitest/node'
// before a browser fs command
const allowed = isFileLoadingAllowed(viteConfig, slash(resolve(root, path)))
if (!allowed) throw new Error(`Path outside server.fs.allow: ${path}`)

Try / catch

try {
  await readFile(path)
} catch (e) {
  if (/Access denied/i.test(String((e as Error).message))) {
    // surface a config hint
    throw new Error(`Add '${dirOf(path)}' to server.fs.allow`)
  }
  throw e
}

Prevention

When it happens

Trigger: Calling a browser fs command (readFile, writeFile, _fileInfo, or screenshot file access) on a path that is not within the Vite-allowed filesystem roots. The path is normalized via slash() and checked against both Vite server configs.

Common situations: Tests reading fixture files located outside the project root; monorepo where the test file references a sibling package outside server.fs.allow; strict fs mode defaulting on after a Vite/Vitest upgrade; absolute paths to /tmp or home.

Related errors


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