JuliusBrussee/caveman · error · Error
cave_vercel_terminal_failure
cave_vercel_terminal_failure
Error message
cave_vercel_terminal_failure
What it means
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.
Source
Thrown at packages/agent/src/adapters.ts:213
export function createVercelAISDKAdapter(
identity: HarnessAdapterIdentity,
agent: VercelToolLoopAgentBinding,
): HarnessAdapter {
assertSupportedUpstream(identity, VERCEL_AI_SDK_VERSION, "vercel", "ai");
return createHarnessAdapter("vercel-ai-sdk", identity, {
package: "ai",
class: "ToolLoopAgent",
method: "generate",
usage: "LanguageModelUsage.v4",
}, async (request) => {
const startedAt = performance.now();
const response = await agent.generate({
prompt: request.prompt,
...(request.signal === undefined ? {} : { abortSignal: request.signal }),
});
if (response.error !== undefined || terminalFinishReason(response.finishReason) === false) {
throw new Error("cave_vercel_terminal_failure");
}
const expected = expectedProviderModel(request.plan);
const actualModel = normalizedResponseModel(response.response?.modelId, expected.provider);
return harnessExecution({
request,
text: response.text,
provider: expected.provider,
model: actualModel,
usage: usageFromAISDK(response.usage, request.plan.reasoning !== "none"),
latencyMs: Math.round(performance.now() - startedAt),
});
});
}
export interface EveMessageResponseBinding {
result(): Promise<{
message: string | undefined;
status: "completed" | "failed" | "waiting";View on GitHub (pinned to 27d5a3981a)
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.
Example fix
# before CAVEMAN_HOME=/var/lib/caveman caveman-shrink < in.json # create /var/lib/caveman: permission denied # after sudo mkdir -p /var/lib/caveman && sudo chown "$USER" /var/lib/caveman CAVEMAN_HOME=/var/lib/caveman caveman-shrink < in.json
Defensive patterns
Strategy: validation
Validate before calling
// Go callers: ensure the CAVEMAN_HOME parent exists and is writable
home := os.Getenv("CAVEMAN_HOME")
if home == "" {
h, _ := os.UserHomeDir()
home = filepath.Join(h, ".caveman")
}
if fi, err := os.Stat(filepath.Dir(home)); err != nil || !fi.IsDir() {
return fmt.Errorf("cannot create %s: parent missing or not a directory", home)
}
if err := os.MkdirAll(home, 0o700); err != nil {
return fmt.Errorf("pre-create %s failed: %w", home, err)
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- cave_harness_aborted
- caveman agent: invalid .caveman/provider.json
- ${envVar} does not point to an executable: ${explicit}
- cache-replay: verifier command must be an existing regular f
- native session key mkdir: %w
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/5be1f7fe47be181a.
Report an issue: GitHub.