JuliusBrussee/caveman · error · Error

cave_harness_aborted

cave_harness_aborted

Error message

cave_harness_aborted

What it means

When no store is supplied via config, Shrink resolves the recovery-store path (CAVEMAN_CCR_DB, else CAVEMAN_HOME/ccr.db, else ~/.caveman/ccr.db) and opens it with ccr.Open. Any failure to open the SQLite-backed recovery store is wrapped as 'open recovery store %q: %w', preserving the path and underlying error. This is an environment problem (missing dir, permissions, corrupt db, locked db), not an input problem.

Source

Thrown at packages/agent/src/adapters.ts:129

    version: identity.adapterVersion,
    manifest,
    contractSHA256,
    async run(request: HarnessRequest): Promise<HarnessResult> {
      const frozenRequest = snapshotRequest(request);
      const prepared = prepareLockedHarnessExecution({
        build: frozenRequest.build,
        harness: id,
        adapterVersion: identity.adapterVersion,
        upstreamVersion: identity.upstreamVersion,
        contextIR: frozenRequest.contextIR,
        plan: frozenRequest.plan,
      });
      const { build, planSHA256, contextIRSHA256 } = prepared;
      if (typeof frozenRequest.prompt !== "string" || frozenRequest.prompt.length === 0 ||
          typeof frozenRequest.runID !== "string" || frozenRequest.runID.length === 0) {
        throw new Error("cave_harness_request_invalid");
      }
      if (isAborted(frozenRequest.signal)) throw new Error("cave_harness_aborted");
      validateTransformEvidence(frozenRequest, frozenRequest.plan);
      const execution = snapshotExecution(await invoke(frozenRequest));
      if (isAborted(frozenRequest.signal)) throw new Error("cave_harness_aborted");
      validateExecution(execution, frozenRequest.plan);
      return {
        terminal: execution.terminal,
        text: execution.text,
        provider: execution.provider,
        model: execution.model,
        inputTokens: execution.inputTokens,
        outputTokens: execution.outputTokens,
        cacheReadTokens: execution.cacheReadTokens,
        cacheWriteTokens: execution.cacheWriteTokens,
        reasoningTokens: execution.reasoningTokens,
        totalTokens: execution.totalTokens,
        costUsd: execution.costUsd,
        usageBasis: execution.usageBasis,
        priceBasis: execution.priceBasis,

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Check that the resolved path is a writable location: touch the parent dir as the same user; free disk space.
  2. Verify CAVEMAN_CCR_DB (if set) points to a SQLite file path in an existing directory, not a directory itself.
  3. If the db is corrupt, move the old ccr.db aside and let the tool recreate it (recovery history is lost).
  4. For concurrent runs, serialize shrinks or give each process its own CAVEMAN_CCR_DB.

Example fix

# before
CAVEMAN_CCR_DB=/var/lib/caveman/ccr.db caveman-shrink < in.json
# fails if /var/lib/caveman is not writable

# after
mkdir -p /var/lib/caveman && chown appuser /var/lib/caveman
CAVEMAN_CCR_DB=/var/lib/caveman/ccr.db caveman-shrink < in.json
Defensive patterns

Strategy: try-catch

Validate before calling

// Go callers of Shrink: verify the store path is openable first
path := os.Getenv("CAVEMAN_CCR_DB")
if path == "" {
    path = filepath.Join(homeDir(), ".caveman", "ccr.db")
}
if fi, err := os.Stat(filepath.Dir(path)); err != nil || !fi.IsDir() {
    return fmt.Errorf("recovery store dir not ready: %s", filepath.Dir(path))
}

Try / catch

store, closeStore, err := openStore(cfg)
if err != nil {
    // env problem: report path + cause, fall back to store-less shrink if the API allows
    if strings.HasPrefix(err.Error(), "open recovery store") {
        return nil, fmt.Errorf("recovery store unavailable (check CAVEMAN_CCR_DB path, permissions, concurrent processes): %w", err)
    }
    return nil, err
}

Prevention

When it happens

Trigger: Running Shrink with cfg.store == nil and cfg.path == "" while ccr.Open(path) fails: unwritable ~/.caveman, a CAVEMAN_CCR_DB pointing to a directory or non-SQLite file, a corrupt ccr.db, or another process holding an exclusive SQLite lock.

Common situations: CI containers running as a read-only-root user so ~/.caveman cannot be written; CAVEMAN_CCR_DB set to a path on a full disk; two concurrent shrink processes racing on the same ccr.db; a stale lock file after a crash.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/29cd426e5807a7c1. Report an issue: GitHub.