{"record":{"id":"5be1f7fe47be181a","repo":"JuliusBrussee/caveman","slug":"cave-vercel-terminal-failure","errorCode":"cave_vercel_terminal_failure","errorMessage":"cave_vercel_terminal_failure","messagePattern":"cave_vercel_terminal_failure","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/agent/src/adapters.ts","lineNumber":213,"sourceCode":"\nexport function createVercelAISDKAdapter(\n  identity: HarnessAdapterIdentity,\n  agent: VercelToolLoopAgentBinding,\n): HarnessAdapter {\n  assertSupportedUpstream(identity, VERCEL_AI_SDK_VERSION, \"vercel\", \"ai\");\n  return createHarnessAdapter(\"vercel-ai-sdk\", identity, {\n    package: \"ai\",\n    class: \"ToolLoopAgent\",\n    method: \"generate\",\n    usage: \"LanguageModelUsage.v4\",\n  }, async (request) => {\n    const startedAt = performance.now();\n    const response = await agent.generate({\n      prompt: request.prompt,\n      ...(request.signal === undefined ? {} : { abortSignal: request.signal }),\n    });\n    if (response.error !== undefined || terminalFinishReason(response.finishReason) === false) {\n      throw new Error(\"cave_vercel_terminal_failure\");\n    }\n    const expected = expectedProviderModel(request.plan);\n    const actualModel = normalizedResponseModel(response.response?.modelId, expected.provider);\n    return harnessExecution({\n      request,\n      text: response.text,\n      provider: expected.provider,\n      model: actualModel,\n      usage: usageFromAISDK(response.usage, request.plan.reasoning !== \"none\"),\n      latencyMs: Math.round(performance.now() - startedAt),\n    });\n  });\n}\n\nexport interface EveMessageResponseBinding {\n  result(): Promise<{\n    message: string | undefined;\n    status: \"completed\" | \"failed\" | \"waiting\";","sourceCodeStart":195,"sourceCodeEnd":231,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/packages/agent/src/adapters.ts#L195-L231","documentation":"defaultCCRPath creates the CAVEMAN_HOME directory (or ~/.caveman) with MkdirAll(0700) so the first run succeeds; any mkdir failure is wrapped as 'create %s: %w'. This is a filesystem permission or path problem: the parent path is not writable, a path component is a file, or the filesystem is read-only.","triggerScenarios":"Calling Shrink with CAVEMAN_HOME set to a location whose parents are not writable (e.g. /etc/caveman as non-root), CAVEMAN_HOME pointing at an existing regular file, or a read-only filesystem such as a container rootfs.","commonSituations":"Setting CAVEMAN_HOME=/var/lib/caveman without creating/granting it; pointing CAVEMAN_HOME into a path where a file already exists; read-only root filesystems in hardened Kubernetes pods; disk quota exhaustion.","solutions":["Pre-create the directory and grant write access to the running user: mkdir -p /var/lib/caveman && chown <user> /var/lib/caveman.","Point CAVEMAN_HOME (or CAVEMAN_CCR_DB) at a writable volume, e.g. an emptyDir or mounted PVC in Kubernetes.","Remove any regular file occupying the intended directory path."],"exampleFix":"# before\nCAVEMAN_HOME=/var/lib/caveman caveman-shrink < in.json\n# create /var/lib/caveman: permission denied\n\n# after\nsudo mkdir -p /var/lib/caveman && sudo chown \"$USER\" /var/lib/caveman\nCAVEMAN_HOME=/var/lib/caveman caveman-shrink < in.json","handlingStrategy":"validation","validationCode":"// Go callers: ensure the CAVEMAN_HOME parent exists and is writable\nhome := os.Getenv(\"CAVEMAN_HOME\")\nif home == \"\" {\n    h, _ := os.UserHomeDir()\n    home = filepath.Join(h, \".caveman\")\n}\nif fi, err := os.Stat(filepath.Dir(home)); err != nil || !fi.IsDir() {\n    return fmt.Errorf(\"cannot create %s: parent missing or not a directory\", home)\n}\nif err := os.MkdirAll(home, 0o700); err != nil {\n    return fmt.Errorf(\"pre-create %s failed: %w\", home, err)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Provision the caveman home directory in deployment scripts (mkdir + chown) before first run.","In Kubernetes, mount a writable volume at the CAVEMAN_HOME path for read-only root filesystems.","Smoke-test the tool as the runtime user, not root, before shipping the image."],"tags":["filesystem","permissions","environment","configuration"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}