denoland/deno · error · FsError
Not a directory
Error message
Not a directory
What it means
In a compiled (deno compile) binary, paths inside the embedded VFS cannot become the real process working directory, so chdir is emulated: if the VFS target exists and is a directory, the call succeeds as a no-op (Deno.cwd() keeps reporting the old real directory); if the target exists but is not a directory, you get io::ErrorKind::NotADirectory 'Not a directory'.
Source
Thrown at cli/rt/file_system.rs:157
RealFs.cwd()
}
fn tmp_dir(&self) -> FsResult<PathBuf> {
RealFs.tmp_dir()
}
fn chdir(&self, path: &CheckedPath) -> FsResult<()> {
if self.is_vfs_path(path) {
// The process working directory can't actually be changed to a path
// inside the embedded virtual file system, but applications (e.g.
// Next.js standalone builds) commonly chdir into their own directory.
// Verify the target exists and is a directory in the VFS and treat the
// change as a no-op rather than failing with NotSupported. Note that
// Deno.cwd() still reports the previous (real) working directory.
if self.vfs.stat(path)?.as_fs_stat().is_directory {
Ok(())
} else {
Err(FsError::Io(std::io::Error::new(
ErrorKind::NotADirectory,
"Not a directory",
)))
}
} else {
RealFs.chdir(path)
}
}
fn umask(&self, mask: Option<u32>) -> FsResult<u32> {
RealFs.umask(mask)
}
fn open_sync(
&self,
path: &CheckedPath,
options: OpenOptions,
) -> FsResult<Rc<dyn DenoFile>> {View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Point chdir at an actual directory (e.g. the directory of the entry module: new URL('.', import.meta.url))
- Guard with Deno.statSync first and check .isDirectory before chdir
- Remember that in compiled binaries chdir into the VFS is a no-op for the OS — code relying on the CWD actually changing (relative file writes) must instead resolve paths explicitly against the VFS root
Example fix
// before (compiled binary; mod.ts is a file)
Deno.chdir(new URL('.', import.meta.url).pathname + 'mod.ts');
// after
const dir = new URL('.', import.meta.url).pathname;
if (Deno.statSync(dir).isDirectory) Deno.chdir(dir); Defensive patterns
Strategy: validation
Validate before calling
// Safe chdir that tolerates the compiled-VFS no-op semantics
import { isDir } from "./util.ts";
export function chdirSafe(p: string) {
const st = Deno.statSync(p); // follows symlinks
if (!st.isDirectory) throw new Error(`chdir target is not a directory: ${p}`);
Deno.chdir(p);
} Type guard
function isDirectorySync(p: string): boolean {
try { return Deno.statSync(p).isDirectory; } catch { return false; }
} Try / catch
try {
process.chdir(dir); // or Deno.chdir(dir)
} catch (e) {
if (e instanceof Error && /Not a directory/i.test(e.message)) {
// derive the real directory of the current module instead
Deno.chdir(new URL(".", import.meta.url).pathname);
} else throw e;
} Prevention
- Derive directories from module URLs (new URL('.', import.meta.url)), never from file paths
- stat-check isDirectory before every chdir in code that runs compiled
- Remember compiled VFS chdir is a no-op: never rely on relative writes after it
When it happens
Trigger: A compiled app calling Deno.chdir (or process.chdir in Node-compat code, or a dependency like Next.js standalone doing chdir(__dirname)) where the VFS path resolves to a file or symlink-to-file rather than a directory; e.g. chdir('/deno-dir/src/mod.ts') or a __dirname computed to point at a file.
Common situations: Ported Node scripts that chdir into paths derived from import.meta/require paths and landing on files; case-sensitivity or symlink differences making a path that is a dir on the host a file in the VFS; hardcoded absolute paths from the build machine baked into the compiled app.
Related errors
- {} is not supported for an embedded deno compile file
- path not found (outside root): {}
- path not found (symlink not dir): {}
- Unexpected 'name' field in options, bench name is already pr
- Unexpected second argument to Deno.bench()
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/005b32f1eb3727d4.
Report an issue: GitHub.