paperclipai/paperclip · error

Remote Codex working directory must be a normalized absolute

Error message

Remote Codex working directory must be a normalized absolute path

What it means

When the working-directory authority is `remote_runner`, the path is interpreted on a remote host, so local path resolution is not used. Instead the validator requires a POSIX absolute, normalized path (no `..` segments, no trailing or doubled slashes) with no control characters, guaranteeing the remote runner receives an unambiguous location.

Source

Thrown at packages/paperclip-runner/src/drivers/codex/codex-boundaries.ts:129

    ) {
      throw new Error(
        "Codex working directory is outside the assigned workspace",
      );
    }
  }
  return resolved;
}

function validateRemoteRunnerWorkingDirectory(
  workingDirectory: string,
  environment: NodeJS.ProcessEnv,
): string {
  if (
    !posix.isAbsolute(workingDirectory) ||
    posix.normalize(workingDirectory) !== workingDirectory ||
    /[\u0000-\u001f\u007f]/u.test(workingDirectory)
  ) {
    throw new Error(
      "Remote Codex working directory must be a normalized absolute path",
    );
  }
  if (workingDirectory === posix.parse(workingDirectory).root) {
    throw new Error("Codex working directory cannot be a filesystem root");
  }
  const configuredRoot = environment.PAPERCLIP_WORKSPACE_CWD?.trim();
  if (!configuredRoot) {
    throw new Error(
      "Remote Codex working directory requires an assigned workspace",
    );
  }
  if (
    !posix.isAbsolute(configuredRoot) ||
    posix.normalize(configuredRoot) !== configuredRoot
  ) {
    throw new Error(
      "Assigned remote workspace must be a normalized absolute path",

View on GitHub (pinned to 01ad858492)

Solutions

  1. Send a posix-normalized absolute path: posix.normalize(posix.join(...)) and verify posix.isAbsolute
  2. Strip control characters/whitespace from the path at the source
  3. For remote runners, build paths with path.posix (not the local path module)

Example fix

// before
validateCodexWorkingDirectory("/workspaces/" + id + "/", env, "remote_runner");
// after
import { posix } from "node:path";
const p = posix.normalize(`/workspaces/${id}`);
validateCodexWorkingDirectory(p, env, "remote_runner");
Defensive patterns

Strategy: validation

Validate before calling

import { posix } from "node:path";
function validRemoteCwd(p: string): boolean {
  return posix.isAbsolute(p) && posix.normalize(p) === p && !/[\u0000-\u001f\u007f]/u.test(p) && p !== posix.parse(p).root;
}
if (!validRemoteCwd(cwd)) throw new Error("remote cwd must be a normalized absolute POSIX path");

Type guard

function isNormalizedAbsolutePosixPath(v: unknown): v is string {
  return typeof v === "string" && posix.isAbsolute(v) && posix.normalize(v) === v && !/[\u0000-\u001f\u007f]/u.test(v);
}

Try / catch

try {
  validateCodexWorkingDirectory(cwd, env, "remote_runner");
} catch (err) {
  if (err.message.includes("must be a normalized absolute path")) {
    throw new ConfigError(`remote cwd "${cwd}" is relative or non-normalized; build paths with path.posix`);
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling `validateCodexWorkingDirectory` with `authority: "remote_runner"` and a relative path ("workspaces/foo"), a non-normalized path ("/workspaces/../foo", "/workspaces//foo", "/workspaces/foo/"), or a path containing control characters like a newline.

Common situations: Passing a Windows-style or local absolute path to a remote runner; concatenating paths without normalization; user input carrying a trailing newline from a form or env var.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10). Data as JSON: /api/errors/91fe5312137443a3. Report an issue: GitHub.