paperclipai/paperclip · error · Error

Working directory is not a directory: "${cwd}"

Error message

Working directory is not a directory: "${cwd}"

What it means

Thrown by ensureAbsoluteDirectory's assertDirectory when the path exists but fs.stat reports it is not a directory (e.g. it is a regular file, socket, or symlink to a file). The working directory must be an actual directory for spawning and file ops, so a file-at-that-path is rejected.

Source

Thrown at packages/adapter-utils/src/server-utils.ts:2430

export function ensurePathInEnv(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {
  if (typeof env.PATH === "string" && env.PATH.length > 0) return env;
  if (typeof env.Path === "string" && env.Path.length > 0) return env;
  return { ...env, PATH: defaultPathForPlatform() };
}

export async function ensureAbsoluteDirectory(
  cwd: string,
  opts: { createIfMissing?: boolean } = {},
) {
  if (!path.isAbsolute(cwd)) {
    throw new Error(`Working directory must be an absolute path: "${cwd}"`);
  }

  const assertDirectory = async () => {
    const stats = await fs.stat(cwd);
    if (!stats.isDirectory()) {
      throw new Error(`Working directory is not a directory: "${cwd}"`);
    }
  };

  try {
    await assertDirectory();
    return;
  } catch (err) {
    const code = (err as NodeJS.ErrnoException).code;
    if (!opts.createIfMissing || code !== "ENOENT") {
      if (code === "ENOENT") {
        throw new Error(`Working directory does not exist: "${cwd}"`);
      }
      throw err instanceof Error ? err : new Error(String(err));
    }
  }

  try {
    await fs.mkdir(cwd, { recursive: true });

View on GitHub (pinned to 67001ec6eb)

Solutions

  1. Inspect the path with `ls -la <cwd>` to see whether it is a file or a bad symlink, then remove or rename it.
  2. If a build step produced a file where a directory is expected, fix that step to mkdir instead of write.
  3. Choose a non-colliding directory name for the working directory.
  4. Resolve symlinks (fs.realpath) earlier to detect a file target before calling ensureAbsoluteDirectory.
Defensive patterns

Strategy: validation

Validate before calling

const st = await fs.stat(cwd);
if (!st.isDirectory()) {
  throw new Error(`cwd is not a directory: ${cwd} (mode ${st.mode})`);
}

Prevention

When it happens

Trigger: ensureAbsoluteDirectory called with an absolute cwd that resolves to an existing non-directory entry — most often a file created earlier with the same name (e.g. a lock file, a build artifact, a mistakenly-created file instead of folder).

Common situations: A previous step wrote a file named identically to the intended directory (e.g. 'build' is a file); a symlink points at a file; a socket/device node occupies the path; the path collides with an artifact like 'dist'.

Related errors


AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12). Data as JSON: /api/errors/7175a170c18c1213. Report an issue: GitHub.