paperclipai/paperclip · error

Sandbox path alias target "${aliasTarget}" does not exist.

Error message

Sandbox path alias target "${aliasTarget}" does not exist.

What it means

Thrown in the pathAliases loop after the workspace-containment check when pathExists(aliasTarget) returns false. The alias passed validation but its host-side source does not exist; bwrap would fail to bind it, so the library surfaces the missing file with the offending path in the message.

Source

Thrown at packages/adapter-utils/src/local-process-sandbox.ts:423

    for (const systemPath of SYSTEM_READ_PATHS) await mount(systemPath, "ro");
    for (const executablePath of await executableReadPaths(input.executable)) await mount(executablePath, "ro");
    if (networkScope === "allowlist") {
      for (const nodePath of await executableReadPaths(process.execPath)) await mount(nodePath, "ro");
    }
    for (const managedPath of input.options.managedPaths ?? []) await mount(managedPath.path, managedPath.access);
    for (const extraPath of input.options.extraPaths ?? []) await mount(extraPath.path, extraPath.access);
    await mount(workspaceDir, "rw");
    for (const [index, alias] of (input.options.pathAliases ?? []).entries()) {
      const aliasPath = normalizeAbsolutePath(alias.path, `Sandbox pathAliases[${index}].path`);
      const aliasTarget = normalizeAbsolutePath(alias.target, `Sandbox pathAliases[${index}].target`);
      const relativeTarget = path.relative(workspaceDir, aliasTarget);
      if (relativeTarget.startsWith("..") || path.isAbsolute(relativeTarget)) {
        throw new Error(
          `Sandbox path alias "${aliasPath}" must target the synchronized workspace "${workspaceDir}".`,
        );
      }
      if (!(await pathExists(aliasTarget))) {
        throw new Error(`Sandbox path alias target "${aliasTarget}" does not exist.`);
      }
      addParentDirectories(args, created, aliasPath);
      args.push("--bind", aliasTarget, aliasPath);
      created.add(aliasPath);
    }

    if (networkScope === "allowlist") {
      const tempDir = await createNetworkProxyTempDir();
      const socketPath = path.join(tempDir, "proxy.sock");
      const bridgePath = path.join(tempDir, "bridge.cjs");
      await fs.writeFile(bridgePath, await createNetworkProxyBridge(), { mode: 0o500 });
      const proxy = await startNetworkAllowlistProxy(
        input.options.networkAllowlist ?? [],
        input.options.networkTrustedUrls ?? [],
        socketPath,
      ).catch(async (error) => {
        await fs.rm(tempDir, { recursive: true, force: true });
        throw error;

View on GitHub (pinned to 67001ec6eb)

Solutions

  1. Verify the path with fs.exists() / fs.stat() before calling buildLocalProcessSandboxSpawnTarget and create or fix it if missing.
  2. Ensure any asset staging step that produces the alias target has awaited completion before sandbox spawn.
  3. If the target is optional, drop the alias entry when pathExists returns false rather than letting the sandbox builder throw.
  4. On containers, check that the volume mount backing the target is present (docker inspect, mount(8)) — a missing mount is the usual cause of a path that exists on the host but not in the container.

Example fix

// before
pathAliases: [{ path: "/work/config.json", target: "/srv/work/config.json" }]
// config.json does not yet exist when buildLocalProcessSandboxSpawnTarget runs

// after
await fs.writeFile("/srv/work/config.json", JSON.stringify(config));
pathAliases: [{ path: "/work/config.json", target: "/srv/work/config.json" }]
Defensive patterns

Strategy: validation

Validate before calling

async function assertPathAliasTargetsExist(aliases: { path: string; target: string }[]): Promise<void> {
  for (const alias of aliases) {
    if (!await pathExists(alias.target)) {
      throw new Error(`Alias target missing: ${alias.target}`);
    }
  }
}

await assertPathAliasTargetsExist(input.options.pathAliases ?? []);

Try / catch

try {
  return await buildLocalProcessSandboxSpawnTarget(input);
} catch (error) {
  if (error instanceof Error && error.message.includes("path alias target") && error.message.includes("does not exist")) {
    // drop the missing alias and retry, or wait for staging to finish
    input.options.pathAliases = (input.options.pathAliases ?? []).filter((a) => pathExistsSync(a.target));
    return buildLocalProcessSandboxSpawnTarget(input);
  }
  throw error;
}

Prevention

When it happens

Trigger: pathAliases reference a target that has not been created yet, was deleted between config load and sandbox spawn, lives on a mount that is not present in the current container, or is misspelled. The check at local-process-sandbox.ts:422-424 runs after normalizeAbsolutePath and the workspace-containment check, so the path is known to be well-formed and inside the workspace.

Common situations: Asset staging that runs in parallel with sandbox spawn and has not finished writing the alias target; symlink targets whose link exists but whose referent is missing; Docker volume mounts that differ between dev and prod; or simple typos in the configured target path.

Related errors


AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12). Data as JSON: /api/errors/b7070ea46f32130b. Report an issue: GitHub.