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
- Send a posix-normalized absolute path: posix.normalize(posix.join(...)) and verify posix.isAbsolute
- Strip control characters/whitespace from the path at the source
- 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
- Always build remote paths with node:path posix helpers, never the platform path module
- Trim/sanitize user-supplied path fragments (strip newlines, trailing slashes)
- Add a unit test asserting remote cwd candidates survive posix.normalize unchanged
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
- [opencode-local] Remote `opencode models` returned no models
- Invalid status '${String(rawStatus)}'. Must be one of: ${PLU
- "tool" is required and must be a string
- "runContext" is required and must be an object
- "runContext" must include agentId, runId, companyId, and pro
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/91fe5312137443a3.
Report an issue: GitHub.