{"record":{"id":"12840d5756efb65e","repo":"paperclipai/paperclip","slug":"paperclip-opencode-runtime-dir-is-required","errorCode":null,"errorMessage":"PAPERCLIP_OPENCODE_RUNTIME_DIR is required","messagePattern":"PAPERCLIP_OPENCODE_RUNTIME_DIR is required","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/src/cli/opencode-app-server-proxy.ts","lineNumber":81,"sourceCode":"  return new Promise((resolveValue, reject) =>\n    pending.set(id, { resolve: resolveValue, reject }),\n  );\n}\n\nfunction record(value: unknown): Record<string, unknown> {\n  return typeof value === \"object\" && value !== null && !Array.isArray(value)\n    ? (value as Record<string, unknown>)\n    : {};\n}\n\nfunction text(value: unknown, fallback = \"\"): string {\n  return typeof value === \"string\" ? value : fallback;\n}\n\nfunction runtimeDirectory(): string {\n  const configured = process.env.PAPERCLIP_OPENCODE_RUNTIME_DIR?.trim();\n  if (!configured)\n    throw new Error(\"PAPERCLIP_OPENCODE_RUNTIME_DIR is required\");\n  return resolve(configured);\n}\n\nasync function open(\n  params: Record<string, unknown>,\n  resume: boolean,\n): Promise<Record<string, unknown>> {\n  if (session)\n    return threadResponse(\n      session.ids().providerSessionId ?? session.ids().driverSessionId,\n    );\n  cwd = resolve(text(params.cwd, process.cwd()));\n  const model = text(params.model);\n  if (!model.includes(\"/\"))\n    throw new Error(\"OpenCode proxy requires model in provider/model form\");\n  activeModel = model;\n  const dynamicTools = Array.isArray(params.dynamicTools)\n    ? params.dynamicTools.map(record)","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/src/cli/opencode-app-server-proxy.ts#L63-L99","documentation":"The OpenCode app-server proxy locates its runtime working directory exclusively through the PAPERCLIP_OPENCODE_RUNTIME_DIR environment variable; runtimeDirectory() throws if the variable is unset or only whitespace, because the proxy cannot function without a resolved runtime directory.","triggerScenarios":"Calling open() (directly or via handle) when process.env.PAPERCLIP_OPENCODE_RUNTIME_DIR is missing, empty, or contains only spaces.","commonSituations":"Launching the proxy outside the runnerd-supervised environment; a spawn wrapper forgetting to forward the parent's env; shell running with a sanitized environment (systemd, cron, CI).","solutions":["Export PAPERCLIP_OPENCODE_RUNTIME_DIR to the runtime directory path before starting the proxy","Ensure the supervisor (runnerd) passes its full env to the child process","Fail fast in the launcher if the var is absent, with a clear message"],"exampleFix":"// before\nspawn('opencode-app-server-proxy', args);\n// after\nspawn('opencode-app-server-proxy', args, { env: { ...process.env, PAPERCLIP_OPENCODE_RUNTIME_DIR: runtimeDir } });","handlingStrategy":"validation","validationCode":"if (!process.env.PAPERCLIP_OPENCODE_RUNTIME_DIR?.trim()) throw new Error('set PAPERCLIP_OPENCODE_RUNTIME_DIR before starting the proxy');","typeGuard":"function hasRuntimeDir(env: NodeJS.ProcessEnv): env is NodeJS.ProcessEnv & { PAPERCLIP_OPENCODE_RUNTIME_DIR: string } {\n  return typeof env.PAPERCLIP_OPENCODE_RUNTIME_DIR === 'string' && env.PAPERCLIP_OPENCODE_RUNTIME_DIR.trim().length > 0;\n}","tryCatchPattern":"try { await proxy.handle(req); }\ncatch (e) { if (String(e.message).includes('PAPERCLIP_OPENCODE_RUNTIME_DIR is required')) { console.error('Start via runnerd or export PAPERCLIP_OPENCODE_RUNTIME_DIR'); } else throw e; }","preventionTips":["Launch the proxy only through runnerd, which supplies the env","In spawn wrappers, always spread the parent env and add required vars","Add a startup env check with a clear error before any request handling"],"tags":["env","config","opencode"],"backgroundTag":"missing-env-var","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"}