paperclipai/paperclip · error

Remote Codex working directory does not match the assigned w

Error message

Remote Codex working directory does not match the assigned workspace

What it means

For remote runners, the controller cannot inspect the provider-owned filesystem, so the facade is pinned to exactly the assigned workspace: the requested working directory must equal the trimmed PAPERCLIP_WORKSPACE_CWD string. This throws when the two differ in any way, meaning the caller attempted to run Codex outside the single assigned remote workspace.

Source

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

  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",
    );
  }
  // The controller cannot inspect a provider-owned filesystem. Pin the facade
  // to the exact remote workspace while runnerd validates existence, type, and
  // canonical identity inside the authoritative filesystem before launch.
  if (workingDirectory !== configuredRoot) {
    throw new Error(
      "Remote Codex working directory does not match the assigned workspace",
    );
  }
  return workingDirectory;
}

function canonicalConfiguredPath(value: string | undefined): string | null {
  const configured = value?.trim();
  if (!configured) return null;
  return canonicalPathWithMissingTail(resolve(configured));
}

function canonicalPathWithMissingTail(path: string): string {
  let cursor = path;
  const missing: string[] = [];
  while (true) {
    try {
      return resolve(realpathSync.native(cursor), ...missing);

View on GitHub (pinned to 01ad858492)

Solutions

  1. Pass exactly process.env.PAPERCLIP_WORKSPACE_CWD (trimmed) as the remote working directory — the workspace root, not a subpath.
  2. Regenerate the run config after workspace reassignment so the recorded working directory matches the currently assigned workspace.
  3. Convert local paths to the remote workspace path before remote validation; never resolve the remote path on the local filesystem.
  4. Compare with string equality in your own code first (assert(workingDirectory === env.PAPERCLIP_WORKSPACE_CWD?.trim())) to catch drift early.

Example fix

// before
const cwd = realpathSync.native(process.env.PAPERCLIP_WORKSPACE_CWD + "/subdir");
validateCodexWorkingDirectory(cwd, process.env, "remote_runner");
// after
const cwd = process.env.PAPERCLIP_WORKSPACE_CWD!.trim();
validateCodexWorkingDirectory(cwd, process.env, "remote_runner");
Defensive patterns

Strategy: validation

Validate before calling

const configuredRoot = process.env.PAPERCLIP_WORKSPACE_CWD?.trim();
if (workingDirectory !== configuredRoot) {
  throw new Error(`remote cwd must equal assigned workspace: ${workingDirectory} !== ${configuredRoot}`);
}

Try / catch

try {
  validateCodexWorkingDirectory(workingDirectory, process.env, "remote_runner");
} catch (error) {
  if (error instanceof Error && error.message.includes("does not match the assigned workspace")) {
    console.error(`cwd=${workingDirectory} workspace=${process.env.PAPERCLIP_WORKSPACE_CWD}`);
  }
  throw error;
}

Prevention

When it happens

Trigger: validateCodexWorkingDirectory("/workspaces/other", env, "remote_runner") while env.PAPERCLIP_WORKSPACE_CWD === "/workspaces/issue-42"; also string mismatches like case differences, a trailing slash on one side, or passing the local resolved path instead of the remote workspace path.

Common situations: A controller reusing a local filesystem path (e.g. C:\repo or /home/dev/repo) against a remote runner; a task attempting to cd into a subdirectory of the workspace instead of the workspace root; stale run config referencing a previous workspace after reassignment; locale/case normalization discrepancies on case-insensitive providers.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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