{"record":{"id":"b7070ea46f32130b","repo":"paperclipai/paperclip","slug":"sandbox-path-alias-target-aliastarget-does-no","errorCode":null,"errorMessage":"Sandbox path alias target \"${aliasTarget}\" does not exist.","messagePattern":"Sandbox path alias target \"(.+?)\" does not exist\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/adapter-utils/src/local-process-sandbox.ts","lineNumber":423,"sourceCode":"    for (const systemPath of SYSTEM_READ_PATHS) await mount(systemPath, \"ro\");\n    for (const executablePath of await executableReadPaths(input.executable)) await mount(executablePath, \"ro\");\n    if (networkScope === \"allowlist\") {\n      for (const nodePath of await executableReadPaths(process.execPath)) await mount(nodePath, \"ro\");\n    }\n    for (const managedPath of input.options.managedPaths ?? []) await mount(managedPath.path, managedPath.access);\n    for (const extraPath of input.options.extraPaths ?? []) await mount(extraPath.path, extraPath.access);\n    await mount(workspaceDir, \"rw\");\n    for (const [index, alias] of (input.options.pathAliases ?? []).entries()) {\n      const aliasPath = normalizeAbsolutePath(alias.path, `Sandbox pathAliases[${index}].path`);\n      const aliasTarget = normalizeAbsolutePath(alias.target, `Sandbox pathAliases[${index}].target`);\n      const relativeTarget = path.relative(workspaceDir, aliasTarget);\n      if (relativeTarget.startsWith(\"..\") || path.isAbsolute(relativeTarget)) {\n        throw new Error(\n          `Sandbox path alias \"${aliasPath}\" must target the synchronized workspace \"${workspaceDir}\".`,\n        );\n      }\n      if (!(await pathExists(aliasTarget))) {\n        throw new Error(`Sandbox path alias target \"${aliasTarget}\" does not exist.`);\n      }\n      addParentDirectories(args, created, aliasPath);\n      args.push(\"--bind\", aliasTarget, aliasPath);\n      created.add(aliasPath);\n    }\n\n    if (networkScope === \"allowlist\") {\n      const tempDir = await createNetworkProxyTempDir();\n      const socketPath = path.join(tempDir, \"proxy.sock\");\n      const bridgePath = path.join(tempDir, \"bridge.cjs\");\n      await fs.writeFile(bridgePath, await createNetworkProxyBridge(), { mode: 0o500 });\n      const proxy = await startNetworkAllowlistProxy(\n        input.options.networkAllowlist ?? [],\n        input.options.networkTrustedUrls ?? [],\n        socketPath,\n      ).catch(async (error) => {\n        await fs.rm(tempDir, { recursive: true, force: true });\n        throw error;","sourceCodeStart":405,"sourceCodeEnd":441,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/packages/adapter-utils/src/local-process-sandbox.ts#L405-L441","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Verify the path with fs.exists() / fs.stat() before calling buildLocalProcessSandboxSpawnTarget and create or fix it if missing.","Ensure any asset staging step that produces the alias target has awaited completion before sandbox spawn.","If the target is optional, drop the alias entry when pathExists returns false rather than letting the sandbox builder throw.","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."],"exampleFix":"// before\npathAliases: [{ path: \"/work/config.json\", target: \"/srv/work/config.json\" }]\n// config.json does not yet exist when buildLocalProcessSandboxSpawnTarget runs\n\n// after\nawait fs.writeFile(\"/srv/work/config.json\", JSON.stringify(config));\npathAliases: [{ path: \"/work/config.json\", target: \"/srv/work/config.json\" }]","handlingStrategy":"validation","validationCode":"async function assertPathAliasTargetsExist(aliases: { path: string; target: string }[]): Promise<void> {\n  for (const alias of aliases) {\n    if (!await pathExists(alias.target)) {\n      throw new Error(`Alias target missing: ${alias.target}`);\n    }\n  }\n}\n\nawait assertPathAliasTargetsExist(input.options.pathAliases ?? []);","typeGuard":null,"tryCatchPattern":"try {\n  return await buildLocalProcessSandboxSpawnTarget(input);\n} catch (error) {\n  if (error instanceof Error && error.message.includes(\"path alias target\") && error.message.includes(\"does not exist\")) {\n    // drop the missing alias and retry, or wait for staging to finish\n    input.options.pathAliases = (input.options.pathAliases ?? []).filter((a) => pathExistsSync(a.target));\n    return buildLocalProcessSandboxSpawnTarget(input);\n  }\n  throw error;\n}","preventionTips":["Await all asset staging steps before calling the sandbox builder.","Validate alias targets with fs.stat at config load.","On containers, verify the volume mount backing each target is present before spawn."],"tags":["filesystem","sandbox","paths","staging"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}