paperclipai/paperclip · error
filesystemExtraPaths[${index}] must be an absolute path or {
Error message
filesystemExtraPaths[${index}] must be an absolute path or { path, access } object. What it means
Thrown by parseLocalProcessSandboxExtraPaths when an entry in the filesystemExtraPaths array is neither a string nor a plain object. Strings are accepted (treated as { path: entry, access: "ro" }); plain objects are accepted if they have the right shape; everything else (number, boolean, null, array) is rejected.
Source
Thrown at packages/adapter-utils/src/local-process-sandbox.ts:500
const proxyUrl = `http://127.0.0.1:${SANDBOX_PROXY_PORT}`;
env.HTTP_PROXY = proxyUrl;
env.HTTPS_PROXY = proxyUrl;
env.http_proxy = proxyUrl;
env.https_proxy = proxyUrl;
}
args.push("--chdir", cwd, "--", executable, ...executableArgs);
return { command: bwrapCommand, args, cwd: "/", env, cleanup };
}
export function parseLocalProcessSandboxExtraPaths(value: unknown): LocalProcessSandboxPath[] {
if (!Array.isArray(value)) return [];
return value.map((entry, index) => {
if (typeof entry === "string") {
return { path: normalizeAbsolutePath(entry, `filesystemExtraPaths[${index}]`), access: "ro" };
}
if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
throw new Error(`filesystemExtraPaths[${index}] must be an absolute path or { path, access } object.`);
}
const raw = entry as Record<string, unknown>;
const access = raw.access === "rw" ? "rw" : raw.access === "ro" || raw.access == null ? "ro" : null;
if (!access || typeof raw.path !== "string") {
throw new Error(`filesystemExtraPaths[${index}] must use access "ro" or "rw" and an absolute path.`);
}
return { path: normalizeAbsolutePath(raw.path, `filesystemExtraPaths[${index}].path`), access };
});
}
View on GitHub (pinned to 67001ec6eb)
Solutions
- Provide each entry as either a string ("/usr/lib") or an object ({ path: "/usr/lib", access: "ro" }).
- Filter the array before parsing to drop nulls: entries.filter((e) => e != null).
- Quote YAML entries that look like numbers or booleans to force string parsing.
- Validate the array shape with a schema (zod z.array(z.union([z.string(), z.object({ path: z.string(), access: z.enum(["ro","rw"]).optional() })]))) at the config boundary.
Example fix
// before
parseLocalProcessSandboxExtraPaths(["/usr/lib", 42, { path: "/etc", access: "ro" }]);
// after
parseLocalProcessSandboxExtraPaths(["/usr/lib", "/opt/data", { path: "/etc", access: "ro" }]); Defensive patterns
Strategy: type-guard
Validate before calling
function isExtraPathEntry(value: unknown): value is string | { path: string; access?: string } {
if (typeof value === "string") return true;
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
const raw = value as Record<string, unknown>;
return typeof raw.path === "string" && (raw.access === undefined || raw.access === "ro" || raw.access === "rw");
}
if (!Array.isArray(config.filesystemExtraPaths) || !config.filesystemExtraPaths.every(isExtraPathEntry)) {
throw new Error("filesystemExtraPaths must be string[] or { path, access? }[]");
}
const parsed = parseLocalProcessSandboxExtraPaths(config.filesystemExtraPaths); Type guard
function isLocalProcessSandboxExtraPath(value: unknown): value is string | { path: string; access?: 'ro' | 'rw' } {
if (typeof value === "string") return true;
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
const raw = value as Record<string, unknown>;
return typeof raw.path === "string" && (raw.access === undefined || raw.access === "ro" || raw.access === "rw");
} Try / catch
try {
const parsed = parseLocalProcessSandboxExtraPaths(config.filesystemExtraPaths);
} catch (error) {
if (error instanceof Error && error.message.startsWith("filesystemExtraPaths[")) {
throw new ConfigError(`Invalid filesystemExtraPaths: ${error.message}`, { cause: error });
}
throw error;
} Prevention
- Type the field as (string | { path: string; access?: 'ro' | 'rw' })[] in the config schema.
- Filter nulls before parsing: entries.filter((e) => e != null).
- Quote YAML entries that look numeric/boolean so they parse as strings.
When it happens
Trigger: filesystemExtraPaths: ["/usr/lib", 42, true, null, ["/etc"], new URL("file:///etc")] — every non-string, non-plain-object entry hits the throw at local-process-sandbox.ts:499-501. Arrays are explicitly rejected via Array.isArray(entry).
Common situations: Config loaded from YAML where unquoted values become numbers or booleans; JSON payloads with mixed shapes; a default value that leaks null into the array; or callers that pass a single object instead of an array of objects.
Related errors
- filesystemExtraPaths[${index}] must use access "ro" or "rw"
- networkAllowlist[${index}] must be a string.
- filesystemScope must be "workspace".
- Sandbox cwd "${cwd}" must be inside workspaceDir "${workspac
- Writable sandbox path "${normalizedExtraPath}" is outside sy
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/3bb3a7702a9e7b0d.
Report an issue: GitHub.