{"record":{"id":"2e483745f7ffc98e","repo":"paperclipai/paperclip","slug":"working-directory-must-be-an-absolute-path-cwd","errorCode":null,"errorMessage":"Working directory must be an absolute path: \"${cwd}\"","messagePattern":"Working directory must be an absolute path: \"(.+?)\"","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/adapter-utils/src/server-utils.ts","lineNumber":2424,"sourceCode":"      args: [\"/d\", \"/s\", \"/c\", commandLine],\n    };\n  }\n\n  return { command: executable, args };\n}\n\nexport function ensurePathInEnv(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n  if (typeof env.PATH === \"string\" && env.PATH.length > 0) return env;\n  if (typeof env.Path === \"string\" && env.Path.length > 0) return env;\n  return { ...env, PATH: defaultPathForPlatform() };\n}\n\nexport async function ensureAbsoluteDirectory(\n  cwd: string,\n  opts: { createIfMissing?: boolean } = {},\n) {\n  if (!path.isAbsolute(cwd)) {\n    throw new Error(`Working directory must be an absolute path: \"${cwd}\"`);\n  }\n\n  const assertDirectory = async () => {\n    const stats = await fs.stat(cwd);\n    if (!stats.isDirectory()) {\n      throw new Error(`Working directory is not a directory: \"${cwd}\"`);\n    }\n  };\n\n  try {\n    await assertDirectory();\n    return;\n  } catch (err) {\n    const code = (err as NodeJS.ErrnoException).code;\n    if (!opts.createIfMissing || code !== \"ENOENT\") {\n      if (code === \"ENOENT\") {\n        throw new Error(`Working directory does not exist: \"${cwd}\"`);\n      }","sourceCodeStart":2406,"sourceCodeEnd":2442,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/packages/adapter-utils/src/server-utils.ts#L2406-L2442","documentation":"Thrown by ensureAbsoluteDirectory when the given cwd is not an absolute path (path.isAbsolute returns false). This is the first guard in directory preparation — the orchestrator requires an absolute working directory so that subsequent fs operations and sandbox confinement are unambiguous across platforms. It runs before any existence check.","triggerScenarios":"Calling ensureAbsoluteDirectory(cwd) or a higher-level spawn path that derives cwd from a relative value (e.g. './repo', 'workspace', 'a/b'). path.isAbsolute is platform-aware, so a POSIX-style '/x' on Windows or a Windows 'C:\\x' on Linux can also trip it.","commonSituations":"Caller passed process-relative cwd from a config field that was meant to be resolved; cross-platform path string shipped to the wrong OS; a leading './' or '~' not expanded; cwd read from argv without normalization.","solutions":["Resolve cwd with path.resolve() (or path.posix.resolve for remote POSIX targets) before calling ensureAbsoluteDirectory.","Expand '~' via expandHomePrefix and strip leading './' when collecting the cwd value.","Validate cwd with path.isAbsolute at the config-loading boundary.","For remote POSIX execution use POSIX-style absolute paths regardless of the orchestrator's OS."],"exampleFix":"// before\nawait ensureAbsoluteDirectory('./workspace');\n// after\nawait ensureAbsoluteDirectory(path.resolve('./workspace'));","handlingStrategy":"validation","validationCode":"if (!path.isAbsolute(cwd)) {\n  throw new Error(`cwd must be absolute: ${cwd}`);\n}\n// or just resolve upstream:\ncwd = path.resolve(cwd);","typeGuard":"function isAbsolutePath(p: string): boolean { return typeof p === 'string' && path.isAbsolute(p); }","tryCatchPattern":null,"preventionTips":["Always resolve cwd with path.resolve at the config boundary.","Expand '~' and strip './' before passing cwd.","Use POSIX absolute paths for remote POSIX targets."],"tags":["filesystem","path","validation","working-directory"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}