{"record":{"id":"f37af23df7fb0fe3","repo":"paperclipai/paperclip","slug":"opencode-working-directory-must-not-be-a-filesyste","errorCode":null,"errorMessage":"OpenCode working directory must not be a filesystem root","messagePattern":"OpenCode working directory must not be a filesystem root","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/src/drivers/opencode/opencode-server-driver.ts","lineNumber":2490,"sourceCode":"  ];\n}\n\nfunction sessionRoot(\n  runtimeDirectory: string,\n  normalizedSessionId: string,\n): string {\n  const safe = normalizedSessionId\n    .replace(/[^a-zA-Z0-9._-]/g, \"_\")\n    .slice(0, 120);\n  if (!safe || safe === \".\" || safe === \"..\")\n    throw new Error(\"Invalid normalized OpenCode session id\");\n  return join(resolve(runtimeDirectory), safe);\n}\n\nfunction validateWorkspace(value: string): string {\n  const cwd = resolve(value);\n  if (!value.trim() || cwd === dirname(cwd))\n    throw new Error(\"OpenCode working directory must not be a filesystem root\");\n  return cwd;\n}\n\nfunction validModel(value: string): boolean {\n  const slash = value.indexOf(\"/\");\n  return slash > 0 && slash < value.length - 1;\n}\n\nfunction compareVersion(left: string, right: string): number {\n  const a = left.split(\".\").map(Number);\n  const b = right.split(\".\").map(Number);\n  for (let index = 0; index < 3; index += 1) {\n    if (a[index] !== b[index]) return (a[index] ?? 0) - (b[index] ?? 0);\n  }\n  return 0;\n}\n\nfunction bounded(value: unknown): Record<string, unknown> {","sourceCodeStart":2472,"sourceCodeEnd":2508,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/src/drivers/opencode/opencode-server-driver.ts#L2472-L2508","documentation":"The OpenCode server driver validates that the workspace/working directory passed to it resolves to a real subdirectory, not a filesystem root. It resolves the given path and compares it with its own parent via dirname; if they are equal (or the value is blank), the path is a root like '/' and the driver refuses to run an agent there. This prevents catastrophic sandbox escapes where the agent could operate on the entire filesystem.","triggerScenarios":"Calling the OpenCode driver with workspace '/', '', '   ', or any path whose resolve() equals its dirname (e.g. '/' on POSIX, 'C:\\\\' on Windows); passing an unconfigured or defaulted runtime workspace variable that is empty so resolve('') yields the process cwd root.","commonSituations":"Misconfigured env vars like WORKSPACE=/ in containers where the mount point is the container root; docker run with workspace mounted at /; template substitution leaving an empty workspace string; forgetting to set a project subdirectory when launching the driver programmatically.","solutions":["Set the workspace to a real project subdirectory, not '/' (e.g. /workspace/repo).","Verify the config/env value feeding the workspace parameter is non-empty and points at a directory containing your project.","If running in a container, mount the project at a nested path and reference that nested path.","Add your own pre-check resolve(value) !== dirname(resolve(value)) before constructing the driver to fail with a clearer message."],"exampleFix":"// before\nconst driver = new OpenCodeServerDriver({ workspace: '/' });\n// after\nconst driver = new OpenCodeServerDriver({ workspace: '/workspace/my-project' });","handlingStrategy":"validation","validationCode":"import { resolve, dirname } from 'node:path';\nfunction isRootWorkspace(value: string): boolean {\n  const cwd = resolve(value);\n  return !value.trim() || cwd === dirname(cwd);\n}\nif (isRootWorkspace(config.workspace)) throw new Error(`workspace must be a subdirectory, got: ${config.workspace}`);","typeGuard":"function isRealWorkspace(value: string): value is string {\n  const cwd = resolve(value);\n  return value.trim().length > 0 && cwd !== dirname(cwd) && existsSync(cwd);\n}","tryCatchPattern":"try {\n  const driver = new OpenCodeServerDriver({ workspace: cfg.workspace });\n} catch (err) {\n  if ((err as Error).message.includes('must not be a filesystem root')) {\n    throw new ConfigError(`Invalid workspace '${cfg.workspace}': use a project subdirectory, not a root path`);\n  }\n  throw err;\n}","preventionTips":["Always configure workspace as a concrete project directory, never '/' or a drive root.","Validate workspace at config-load time, before driver construction.","In containers, mount projects at nested paths and reference those paths.","Add a startup assertion that the workspace contains expected project files (e.g. package.json)."],"tags":["configuration","filesystem","validation","opencode"],"backgroundTag":"invalid-argument-value","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}