paperclipai/paperclip · error · Error
Sandbox cwd " " must be inside workspaceDir " ".
Error message
Sandbox cwd "${cwd}" must be inside workspaceDir "${workspaceDir}". What it means
With filesystemScope=workspace, the requested process cwd resolves outside the workspace dir (path.relative escapes), so the sandboxed process would start outside its confined workspace.
Solutions
- Set the sandbox cwd to a path inside workspaceDir.
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at packages/adapter-utils/src/local-process-sandbox.ts:359 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of paperclipai/paperclip@120ae5428f (2026-08-18).
Data as JSON: /api/errors/99eac738bd3f5179.
Report an issue: GitHub.
Appendix: source
Thrown at packages/adapter-utils/src/local-process-sandbox.ts:359
export async function buildLocalProcessSandboxSpawnTarget(input: {
executable: string;
args: string[];
cwd: string;
options: LocalProcessSandboxOptions;
}): Promise<LocalProcessSandboxSpawnTarget> {
if (process.platform !== "linux") {
throw new Error("Local process filesystem and network scopes are currently supported only on Linux.");
}
const filesystemScope = input.options.filesystemScope ?? null;
const networkScope = input.options.networkScope ?? null;
if (!filesystemScope && !networkScope) throw new Error("Local process sandbox requires a filesystem or network scope.");
const workspaceDir = normalizeAbsolutePath(input.options.workspaceDir, "Sandbox workspaceDir");
const cwd = normalizeAbsolutePath(input.cwd, "Sandbox cwd");
if (filesystemScope === "workspace") {
const relativeCwd = path.relative(workspaceDir, cwd);
if (relativeCwd.startsWith("..") || path.isAbsolute(relativeCwd)) {
throw new Error(`Sandbox cwd "${cwd}" must be inside workspaceDir "${workspaceDir}".`);
}
const outboundRestorePaths = (input.options.outboundRestorePaths ?? []).map((candidate, index) =>
normalizeAbsolutePath(candidate, `Sandbox outboundRestorePaths[${index}]`));
for (const [index, extraPath] of (input.options.extraPaths ?? []).entries()) {
if (extraPath.access !== "rw") continue;
const normalizedExtraPath = normalizeAbsolutePath(extraPath.path, `Sandbox extraPaths[${index}].path`);
const relativeToWorkspace = path.relative(workspaceDir, normalizedExtraPath);
const synchronized = !relativeToWorkspace.startsWith("..") && !path.isAbsolute(relativeToWorkspace);
const restored = outboundRestorePaths.some((restorePath) => {
const relative = path.relative(restorePath, normalizedExtraPath);
return !relative.startsWith("..") && !path.isAbsolute(relative);
});
if (!synchronized && !restored) {
throw new Error(
`Writable sandbox path "${normalizedExtraPath}" is outside synchronized workspace "${workspaceDir}" and has no outbound restore mapping.`,
);
}
}View on GitHub (pinned to 120ae5428f)