JuliusBrussee/caveman · error · Error

caveman-code: model must use provider/model format

Error message

caveman-code: model must use provider/model format

What it means

A model identifier given explicitly (argument) or via CAVE_MODEL must be in provider/model form: exactly one '/' that is neither the first nor the last character. 'claude-sonnet', '/model', 'provider/', and 'a/b/c' style values with slash at index 0 or the end are rejected. Note the check only pins slash position, so 'a/b/c' passes; validate your own IDs if you need stricter shapes.

Source

Thrown at packages/agent/src/code.ts:551

      exitCode = code;
      finish();
    });
    // `close` waits for stdio EOF, which a surviving background descendant never
    // gives. `exit` is the command's own answer, so the run settles on it with
    // whatever output arrived rather than waiting on a process it does not own.
    child.once("exit", (code) => {
      exitCode = code;
      setTimeout(finish, EXIT_FLUSH_GRACE_MS).unref();
    });
  });
}

function resolveCodingModelID(explicit: string | undefined): string {
  const requested = explicit ?? process.env.CAVE_MODEL;
  if (requested !== undefined && requested !== "") {
    const slash = requested.indexOf("/");
    if (slash <= 0 || slash === requested.length - 1) {
      throw new Error("caveman-code: model must use provider/model format");
    }
    return requested;
  }
  const configured: string[] = [];
  if (process.env.ANTHROPIC_API_KEY) configured.push("anthropic/claude-sonnet-4-6");
  if (process.env.OPENAI_API_KEY) configured.push("openai/gpt-5.5");
  if (process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY) {
    configured.push("google/gemini-2.5-pro");
  }
  if (configured.length !== 1) {
    throw new Error(
      configured.length === 0
        ? "caveman-code: no supported provider credential found; set ANTHROPIC_API_KEY, OPENAI_API_KEY, or GEMINI_API_KEY"
        : "caveman-code: multiple provider credentials found; set CAVE_MODEL to pick one",
    );
  }
  return configured[0]!;
}

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Format the ID as provider/model, e.g. CAVE_MODEL=anthropic/claude-sonnet-4-6 or openai/gpt-5.5
  2. Check for stray whitespace or a trailing slash in the env var: `printf '%s' "$CAVE_MODEL" | od -c`
  3. Unset CAVE_MODEL entirely to let the credential-based default resolution pick a model

Example fix

# before
export CAVE_MODEL="claude-sonnet-4-6"

# after
export CAVE_MODEL="anthropic/claude-sonnet-4-6"
Defensive patterns

Strategy: validation

Validate before calling

function isValidModelID(id: string): boolean {
  const slash = id.indexOf("/");
  return slash > 0 && slash === id.lastIndexOf("/") && slash < id.length - 1;
}

const requested = process.env.CAVE_MODEL;
if (requested !== undefined && requested !== "" && !isValidModelID(requested)) {
  throw new Error(`CAVE_MODEL must be provider/model, got: ${requested}`);
}

Type guard

function isProviderModelID(v: unknown): v is string {
  return typeof v === "string" && /^[^/\s]+\/[^/\s]+$/.test(v) && !v.includes("//");
}

Prevention

When it happens

Trigger: Setting CAVE_MODEL=claude-sonnet-4-6 (no provider), CAVE_MODEL=/gpt-5.5, CAVE_MODEL=anthropic/ (no model), or passing such a value as the explicit model argument to the coding session.

Common situations: Copy-pasting a bare model name from provider docs; CAVE_MODEL set to an empty-suffix value by a CI variable; using a vendor-specific ID format (e.g. OpenAI model names have no slash).

Related errors


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