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
- Add the directory to server.fs.allow in your Vite/Vitest config, e.g. server: { fs: { allow: ['/abs/path'] } }.
- Move fixture files inside the project root so they fall under the default allowed root.
- 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
- Keep fixtures inside the project root so default fs.allow covers them.
- Whitelist extra roots explicitly via server.fs.allow rather than disabling strict mode.
- Resolve all browser file paths relative to project.config.root.
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
- Cannot modify file "${path}". File writing is disabled becau
- Couldn't write file to fs
- Access denied to "${path}". See Vite config documentation fo
- ${name}Browser name is required. Please, set `test.browser.i
- Browser Mode requires the "provider" to always be specified.
AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03).
Data as JSON: /data/errors/85492aabb21e1b0c.json.
Report an issue: GitHub.