vitest-dev/vitest · error · TypeError
Unexpected file type
Error message
Unexpected file type: ${file} What it means
After resolving a `projects` string entry, `statSync(file)` returned a stats object that is neither a regular file nor a directory (e.g. a FIFO, socket, character/block device, or broken symlink). The source marks this branch `// should never happen` for normal filesystem usage, so hitting it usually indicates an unusual entry in the project tree.
Solutions
- Inspect the offending path with `ls -l` / `stat` and identify what type it is.
- Remove or replace the special file with a real config file or directory.
- If it reproduces on a normal file, file a Vitest issue with the stat details.
Defensive patterns
Strategy: validation
Validate before calling
import { statSync } from 'node:fs'
function assertProjectsEntryIsFileOrDir(file: string) {
const s = statSync(file)
if (!s.isFile() && !s.isDirectory()) {
throw new Error(`projects entry '${file}' is neither a file nor a directory (got mode ${s.mode.toString(8)}). Remove the special file.`)
}
} Prevention
- Keep the project tree free of sockets/pipes/devices.
- Run `git status` / `ls -l` on suspect paths when this fires.
When it happens
Trigger: A `projects` string resolves to a special filesystem object where `stats.isFile()` and `stats.isDirectory()` are both false.
Common situations: Stray named pipe/socket left in the repo; broken symlink; exotic/filesystem (FUSE) reporting odd stat results.
Related errors
- Access denied to " ". See Vite config documentation for…
- Access denied to " ". See Vite config documentation for…
- cannot read when saving inline snapshot
- Couldn't write file to fs
- Failed to create Vitest API token at
AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11).
Data as JSON: /api/errors/49505c0835318272.
Report an issue: GitHub.
Appendix: source
Thrown at packages/vitest/src/node/projects/resolveProjects.ts:1211
)
}
projectsConfigFiles.push(file)
}
// user can specify a directory that should be used as a project
else if (stats.isDirectory()) {
const configFile = resolveDirectoryConfig(file)
if (configFile) {
projectsConfigFiles.push(configFile)
}
else {
const directory = file.at(-1) === '/' ? file : `${file}/`
nonConfigProjectDirectories.push(directory)
}
}
else {
// should never happen
throw new TypeError(`Unexpected file type: ${file}`)
}
}
// if the string is a glob pattern, resolve it later
// ['./packages/*']
else {
projectsGlobMatches.push(stringOption)
}
}
// if the config is inlined, we can resolve it immediately
else if (typeof definition === 'function') {
projectsOptions.push(await definition({
command: 'serve',
mode: parentViteConfig.mode,
isPreview: false,
isSsrBuild: false,
}))
}
// the config is an object or a Promise that returns an objectView on GitHub (pinned to 1fa9837ec2)