{"record":{"id":"992b473a31fcbbcd","repo":"paperclipai/paperclip","slug":"remote-codex-working-directory-does-not-match-the","errorCode":null,"errorMessage":"Remote Codex working directory does not match the assigned workspace","messagePattern":"Remote Codex working directory does not match the assigned workspace","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/src/drivers/codex/codex-boundaries.ts","lineNumber":154,"sourceCode":"  const configuredRoot = environment.PAPERCLIP_WORKSPACE_CWD?.trim();\n  if (!configuredRoot) {\n    throw new Error(\n      \"Remote Codex working directory requires an assigned workspace\",\n    );\n  }\n  if (\n    !posix.isAbsolute(configuredRoot) ||\n    posix.normalize(configuredRoot) !== configuredRoot\n  ) {\n    throw new Error(\n      \"Assigned remote workspace must be a normalized absolute path\",\n    );\n  }\n  // The controller cannot inspect a provider-owned filesystem. Pin the facade\n  // to the exact remote workspace while runnerd validates existence, type, and\n  // canonical identity inside the authoritative filesystem before launch.\n  if (workingDirectory !== configuredRoot) {\n    throw new Error(\n      \"Remote Codex working directory does not match the assigned workspace\",\n    );\n  }\n  return workingDirectory;\n}\n\nfunction canonicalConfiguredPath(value: string | undefined): string | null {\n  const configured = value?.trim();\n  if (!configured) return null;\n  return canonicalPathWithMissingTail(resolve(configured));\n}\n\nfunction canonicalPathWithMissingTail(path: string): string {\n  let cursor = path;\n  const missing: string[] = [];\n  while (true) {\n    try {\n      return resolve(realpathSync.native(cursor), ...missing);","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/src/drivers/codex/codex-boundaries.ts#L136-L172","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pass exactly process.env.PAPERCLIP_WORKSPACE_CWD (trimmed) as the remote working directory — the workspace root, not a subpath.","Regenerate the run config after workspace reassignment so the recorded working directory matches the currently assigned workspace.","Convert local paths to the remote workspace path before remote validation; never resolve the remote path on the local filesystem.","Compare with string equality in your own code first (assert(workingDirectory === env.PAPERCLIP_WORKSPACE_CWD?.trim())) to catch drift early."],"exampleFix":"// before\nconst cwd = realpathSync.native(process.env.PAPERCLIP_WORKSPACE_CWD + \"/subdir\");\nvalidateCodexWorkingDirectory(cwd, process.env, \"remote_runner\");\n// after\nconst cwd = process.env.PAPERCLIP_WORKSPACE_CWD!.trim();\nvalidateCodexWorkingDirectory(cwd, process.env, \"remote_runner\");","handlingStrategy":"validation","validationCode":"const configuredRoot = process.env.PAPERCLIP_WORKSPACE_CWD?.trim();\nif (workingDirectory !== configuredRoot) {\n  throw new Error(`remote cwd must equal assigned workspace: ${workingDirectory} !== ${configuredRoot}`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  validateCodexWorkingDirectory(workingDirectory, process.env, \"remote_runner\");\n} catch (error) {\n  if (error instanceof Error && error.message.includes(\"does not match the assigned workspace\")) {\n    console.error(`cwd=${workingDirectory} workspace=${process.env.PAPERCLIP_WORKSPACE_CWD}`);\n  }\n  throw error;\n}","preventionTips":["Treat PAPERCLIP_WORKSPACE_CWD as the single source of truth; build the cwd from it, never from local paths.","After workspace reassignment, regenerate the run config rather than reusing a stale cwd.","Do not append subpaths for remote runs — remote Codex always runs at the workspace root.","Log both strings on mismatch to catch case/slash discrepancies immediately."],"tags":["path-validation","codex","remote-runner","workspace"],"backgroundTag":"invalid-argument-value","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}