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
- Format the ID as provider/model, e.g. CAVE_MODEL=anthropic/claude-sonnet-4-6 or openai/gpt-5.5
- Check for stray whitespace or a trailing slash in the env var: `printf '%s' "$CAVE_MODEL" | od -c`
- 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
- Validate CAVE_MODEL at startup, not at first session creation
- Document the provider/model format next to every place CAVE_MODEL is set (docker-compose, CI yaml)
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
- cave_harness_model_invalid
- cave_harness_model_identity_missing
- cave_budget_denomination_ambiguous
- cave_budget_max_invalid
- cave_budget_output_floor_invalid
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/00498c795da3e477.
Report an issue: GitHub.