denoland/deno · error

Failed to spawn '{}': cwd is not a directory '{}'

Error message

Failed to spawn '{}': cwd is not a directory '{}'

What it means

Companion check to the 'No such cwd' error in Deno's spawn wrapper: the path in cwd exists (the earlier exists() check passed) but is not a directory — typically a regular file. Spawn aborts with ErrorKind::NotFound and this message before attempting exec.

Source

Thrown at ext/process/lib.rs:1135

        #[allow(clippy::disallowed_methods, reason = "requires real fs")]
        if !cwd.exists() {
          return Err(
            std::io::Error::new(
              std::io::ErrorKind::NotFound,
              format!(
                "Failed to spawn '{}': No such cwd '{}'",
                command_name,
                cwd.to_string_lossy()
              ),
            )
            .into(),
          );
        }

        #[allow(clippy::disallowed_methods, reason = "requires real fs")]
        if !cwd.is_dir() {
          return Err(
            std::io::Error::new(
              std::io::ErrorKind::NotFound,
              format!(
                "Failed to spawn '{}': cwd is not a directory '{}'",
                command_name,
                cwd.to_string_lossy()
              ),
            )
            .into(),
          );
        }
      }

      return Err(ProcessError::SpawnFailed {
        command: command.get_program().to_string_lossy().into_owned(),
        error: Box::new(err.into()),
      });
    }
  };

View on GitHub (pinned to a961cdec3b)

Solutions

  1. Wrap the intended directory: use path.dirname(filePath) instead of the file path itself.
  2. statSync the path and require isDirectory() before spawning; fail with the path in the error.
  3. Delete or rename the stray file if a directory is genuinely expected there and something else created it.
  4. Add a startup assertion for configured cwd values so misconfiguration is caught at boot.

Example fix

// before
const cwd = import.meta.filename; // a file, not a directory
const child = spawn("git", ["status"], { cwd }); // fails: cwd is not a directory

// after
import { dirname } from "node:path";
const cwd = dirname(fileURLToPath(import.meta.url));
const child = spawn("git", ["status"], { cwd });
Defensive patterns

Strategy: validation

Validate before calling

import { statSync } from "node:fs";
if (statSync(cwd, { throwIfNoEntry: false })?.isDirectory() !== true) throw new Error(`cwd must be a directory: ${cwd}`);

Type guard

import { statSync } from "node:fs";
const isDirectoryPath = (p: string): p is `${string}/` => statSync(p, { throwIfNoEntry: false })?.isDirectory() ?? false;

Try / catch

try { spawn(prog, args, { cwd }); } catch (e) { if (/cwd is not a directory/.test(String(e))) throw new Error(`cwd points at a file — use path.dirname(): ${cwd}`); throw e; }

Prevention

When it happens

Trigger: Deno.Command/child_process.spawn with cwd set to a file path: pointing cwd at a script or archive instead of its directory, a path where a file shadows an expected directory name, or a symlink target that is a file.

Common situations: Passing __filename or a config file path where the containing directory was intended; a file created at the location a build step was supposed to make a directory; incorrect path joining (path.join vs path.dirname confusion).

Related errors


AI-assisted analysis of denoland/deno@a961cdec3b (2026-08-20). Data as JSON: /api/errors/14ebc6b4c5b45ba4. Report an issue: GitHub.