JuliusBrussee/caveman · error · Error
caveman-code: multiple provider credentials found; set CAVE_
Error message
caveman-code: multiple provider credentials found; set CAVE_MODEL to pick one
What it means
The credential-based default picks a provider only when the choice is unambiguous. If two or more of ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY/GOOGLE_API_KEY are present, the agent refuses to guess which provider you meant and asks for an explicit CAVE_MODEL.
Source
Thrown at packages/agent/src/code.ts:562
}
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]!;
}
// ---------------------------------------------------------------------------
// Session
// ---------------------------------------------------------------------------
export type SessionMode = "optimized" | "observe-only";
export interface CodingSessionOptions {
conversation?: ConversationState;
cave?: "auto" | "off";
gatewayURL?: string;View on GitHub (pinned to 27d5a3981a)
Solutions
- Set CAVE_MODEL to the provider/model you want, e.g. `export CAVE_MODEL=anthropic/claude-sonnet-4-6`
- Or unset the credentials you do not want used this run: `unset OPENAI_API_KEY GEMINI_API_KEY GOOGLE_API_KEY`
- Scope secrets per-project (direnv, .env per repo) so only one provider's key is present
Example fix
# before: ambiguous export ANTHROPIC_API_KEY=... export OPENAI_API_KEY=... # after: disambiguate export CAVE_MODEL="anthropic/claude-sonnet-4-6"
Defensive patterns
Strategy: validation
Validate before calling
const groups = [
["ANTHROPIC_API_KEY"],
["OPENAI_API_KEY"],
["GEMINI_API_KEY", "GOOGLE_API_KEY"],
] as const;
const active = groups.filter((g) => g.some((v) => process.env[v] && process.env[v] !== ""));
if (active.length > 1 && !process.env.CAVE_MODEL) {
throw new Error(`ambiguous credentials (${active.length} providers); set CAVE_MODEL`);
} Prevention
- Always set CAVE_MODEL in shared/CI environments where multiple provider keys coexist
- Scope one provider's secrets per project via direnv or per-repo .env files
When it happens
Trigger: Having e.g. both ANTHROPIC_API_KEY and OPENAI_API_KEY in the environment (common on dev machines with multiple provider CLIs installed) while CAVE_MODEL is unset.
Common situations: Developer shells with accumulative .envrc/.zshrc exports; CI templates that inject all available secrets 'just in case'; shared machines where different projects use different providers.
Related errors
- caveman-code: no supported provider credential found; set AN
- caveman-code: model must use provider/model format
- multiple provider credentials detected; pass --provider
- cave_budget_denomination_ambiguous
- cave_budget_max_invalid
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/ecfb5c72d7eb1c29.
Report an issue: GitHub.