JuliusBrussee/caveman · error · Error

cave_build_lock_missing: approve required evals, then run np

Error message

cave_build_lock_missing: approve required evals, then run npm run build

What it means

Thrown by the `check` command when `readLock(root)` fails with ENOENT — i.e. `.caveman/agent.lock.json` does not exist in the project root. The lock file is the immutable record of the last successful build; `check` verifies current sources against it and cannot run without it. The message directs you to approve the required eval fixtures and run the build first.

Source

Thrown at packages/agent/src/cli.ts:939

function configuredModelCandidates(baseline: string): string[] {
  const models = new Set<string>([baseline]);
  if (process.env.ANTHROPIC_API_KEY) models.add("anthropic/claude-haiku-4-5");
  if (process.env.OPENAI_API_KEY) models.add("openai/gpt-5.4-mini");
  if (process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY) models.add("google/gemini-2.5-flash");
  return [...models].sort();
}

async function check(args: string[]): Promise<void> {
  const root = process.cwd();
  const configPath = args[0] ?? "caveman.config.ts";
  const loaded = await loadBuildInputs(root, configPath);
  let lock: CaveBuildLock;
  try {
    lock = await readLock(root);
  } catch (error) {
    if ((error as NodeJS.ErrnoException).code === "ENOENT") {
      throw new Error("cave_build_lock_missing: approve required evals, then run npm run build");
    }
    throw error;
  }
  const transformRegistrySha256 = await transformRegistrySHA256();
  const checked = checkLock(lock, {
    sourceSha256: loaded.sourceSha256,
    agentDefinitionSha256: agentDefinitionSHA256(loaded.agent),
    contextIRSha256: contextIRSHA256(await lowerBuildContext(
      root,
      loaded.agent,
    ).then((value) => value.ir)),
    evalSuiteSha256: sha256(stableStringify(loaded.evals.filter((item) => item.approved && item.required))),
    runtimeVersion: FRAMEWORK_VERSION,
    adapterVersion: PI_ADAPTER_VERSION,
    upstreamVersion: PI_UPSTREAM_VERSION,
    transformRegistrySha256,
    catalogSha256: CATALOG_SHA256,
  });

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Approve the required eval fixtures (the build writes `needs_eval` and stops when none are approved), then run `npm run build` to generate `.caveman/agent.lock.json`.
  2. Verify you are in the project root that contains `caveman.config.ts` and `.caveman/`.
  3. In CI, order the pipeline build-before-check or restore the lock artifact from cache.

Example fix

# before
npm run check   # Error: cave_build_lock_missing

# after
npm run build    # after approving required evals
npm run check
Defensive patterns

Strategy: try-catch

Validate before calling

import { access } from "node:fs/promises";
import { resolve } from "node:path";

async function lockExists(root: string): Promise<boolean> {
  try { await access(resolve(root, ".caveman/agent.lock.json")); return true; }
  catch { return false; }
}
// if (!await lockExists(root)) run build first

Try / catch

try {
  await check(args);
} catch (error) {
  if (error instanceof Error && error.message.startsWith("cave_build_lock_missing")) {
    // approve required evals, then run the build command, then re-check
  } else throw error;
}

Prevention

When it happens

Trigger: Running `caveman check` (or `npm run check`) in a fresh clone, after `git clean`, after deleting `.caveman/`, or in a worktree where the build artifact was never generated. Also when the working directory is not the project root the config was built from.

Common situations: Fresh clone / CI checkout without the build step; `.caveman/` gitignored and a colleague runs check before build; switching branches that removed the lock; running the CLI from a subdirectory so `resolve(root, ...)` misses the file.

Related errors


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