JuliusBrussee/caveman · error

caveman build: invalid .caveman/provider.json

Error message

caveman build: invalid .caveman/provider.json

What it means

localProviderModel in packages/agent/src/cli.ts reads .caveman/provider.json to detect a configured model. If the file parses as JSON but readFileSync fails with a non-ENOENT error, or JSON.parse throws a syntax error, the function throws 'caveman build: invalid .caveman/provider.json'. Only a completely absent file is tolerated (returns undefined).

Solutions

  1. Validate and repair the JSON: run `node -e "JSON.parse(require('fs').readFileSync('.caveman/provider.json','utf8'))"` and fix syntax errors (or delete the file if you do not need a pinned model).
  2. Ensure .caveman/provider.json is a regular file, not a directory or symlink to a missing target.
  3. Fix file permissions so the current user can read it (chmod 644 .caveman/provider.json).
  4. Set CAVE_MODEL explicitly so provider detection does not depend on this file.
  5. Remove a stale/truncated provider.json and let the build re-detect the model from provider credentials.

Example fix

// before (invalid JSON)
{ "model": "anthropic/claude-haiku-4-5", }
// after
{ "model": "anthropic/claude-haiku-4-5" }
Defensive patterns

Strategy: try-catch

Validate before calling

const fs = require("fs");
if (fs.existsSync(".caveman/provider.json")) {
  try { JSON.parse(fs.readFileSync(".caveman/provider.json", "utf8")); }
  catch { console.error("provider.json is not valid JSON — fix or delete it"); }
}

Try / catch

try {
  await build();
} catch (e) {
  if (e.message.includes("invalid .caveman/provider.json")) {
    console.error("Repair or remove .caveman/provider.json, or set CAVE_MODEL.");
  } else throw e;
}

Prevention

When it happens

Trigger: Running 'caveman build' when .caveman/provider.json exists but contains invalid JSON (trailing comma, truncated write), or when reading it fails with a permission/IO error (EACCES, EISDIR) rather than ENOENT.

Common situations: A partially written or hand-edited provider.json left invalid JSON behind; the path .caveman/provider.json is actually a directory; restrictive file permissions after copying the repo as another user; editor swap/temp files renamed incorrectly.

Understand the failure class

Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20). Data as JSON: /api/errors/64a2bf4f33f0a067. Report an issue: GitHub.

Appendix: source

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

  };
}

function evalDynamicKinds(evals: readonly EvalDefinition[]): ReadonlySet<ContextKind> {
  const kinds = new Set<ContextKind>();
  if (evals.some((fixture) => fixture.quality.some((grader) => grader.type === "tool_called"))) {
    kinds.add("history");
    kinds.add("tool_result");
  }
  return kinds;
}

function localProviderModel(root: string): string | undefined {
  try {
    const parsed = JSON.parse(readFileSync(resolve(root, ".caveman/provider.json"), "utf8")) as { model?: unknown };
    return typeof parsed.model === "string" ? parsed.model : undefined;
  } catch (error) {
    if ((error as NodeJS.ErrnoException).code === "ENOENT") return undefined;
    throw new Error("caveman build: invalid .caveman/provider.json");
  }
}

function detectedModel(): string {
  const configured = [
    process.env.ANTHROPIC_API_KEY && "anthropic/claude-haiku-4-5",
    process.env.OPENAI_API_KEY && "openai/gpt-5.4-mini",
    (process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY) && "google/gemini-2.5-flash",
  ].filter((value): value is string => typeof value === "string");
  if (configured.length !== 1) {
    throw new Error("caveman build: set CAVE_MODEL when zero or multiple provider credentials exist");
  }
  return configured[0]!;
}

async function loadAgent(path: string): Promise<AgentDefinition> {
  return agentFromImported(await importFresh(path));
}

View on GitHub (pinned to 3ee70a1026)