JuliusBrussee/caveman · error
multiple provider credentials detected; pass --provider
Error message
multiple provider credentials detected; pass --provider
What it means
Provider auto-detection requires an unambiguous signal: if two or more credential env vars (ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY/GOOGLE_API_KEY) are set, the initializer cannot choose for you. In a TTY it would prompt interactively, but non-interactive runs (no TTY on stdin or stdout) throw with this message instead of guessing.
Source
Thrown at packages/create-caveman-agent/src/index.ts:139
"TEMP", "TMP", "TMPDIR", "LANG", "LC_ALL", "LC_CTYPE", "TZ", "CI", "NO_COLOR", "FORCE_COLOR",
"HTTP_PROXY", "HTTPS_PROXY", "NO_PROXY", "http_proxy", "https_proxy", "no_proxy",
"NPM_CONFIG_CACHE", "NPM_CONFIG_REGISTRY", "NPM_CONFIG_USERCONFIG",
"npm_config_cache", "npm_config_registry", "npm_config_userconfig",
]) {
if (process.env[key] !== undefined) env[key] = process.env[key];
}
return env;
}
async function chooseProvider(flag: string | undefined): Promise<Provider> {
if (flag !== undefined) return parseProvider(flag);
const detected: Provider[] = [];
if (process.env.ANTHROPIC_API_KEY) detected.push("anthropic");
if (process.env.OPENAI_API_KEY) detected.push("openai");
if (process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY) detected.push("google");
if (detected.length === 1) return detected[0]!;
if (!process.stdin.isTTY || !process.stdout.isTTY) {
throw new Error(
detected.length === 0
? "no provider credential detected; pass --provider"
: "multiple provider credentials detected; pass --provider",
);
}
const rl = createInterface({ input: process.stdin, output: process.stdout });
try {
const answer = await rl.question("Provider (anthropic/openai/google): ");
return parseProvider(answer);
} finally {
rl.close();
}
}
function projectFiles(name: string, provider: Provider): Record<string, string> {
return {
"package.json": `${JSON.stringify({
name,View on GitHub (pinned to 27d5a3981a)
Solutions
- Pass --provider explicitly to disambiguate.
- Or unset the credentials you do not want used for this run (e.g. `env -u OPENAI_API_KEY npm create ...`) so exactly one remains.
- Keep per-project .env files with only the relevant provider key instead of a global kitchen-sink env.
Example fix
# before: both keys set, CI run fails # after npm create @caveman-ai/agent@latest myapp --provider openai
Defensive patterns
Strategy: validation
Validate before calling
function detectedProviders(): string[] {
const out: string[] = [];
if (process.env.ANTHROPIC_API_KEY) out.push("anthropic");
if (process.env.OPENAI_API_KEY) out.push("openai");
if (process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY) out.push("google");
return out;
}
// require detectedProviders().length <= 1, else pass --provider Prevention
- Scope exported credentials to the provider each project actually uses.
- Pass --provider in automation whenever more than one key may be present.
- Audit shared dotfiles (.zshrc, direnv) for multi-key exports.
When it happens
Trigger: Non-interactive run (piped stdin/stdout, CI) with, e.g., both ANTHROPIC_API_KEY and OPENAI_API_KEY exported, and no --provider flag.
Common situations: Developer shells with several provider keys loaded by a shared .envrc/.zshrc, CI jobs that import a bundle of secrets, or containers built with all keys baked in.
Related errors
- no provider credential detected; pass --provider
- cache-replay: OPENAI_API_KEY unavailable
- cache-replay: ANTHROPIC_API_KEY unavailable
- cache-replay: GEMINI_API_KEY unavailable
- cache-replay: Bedrock bearer token or AWS access credentials
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/f895c19d00e13f0a.
Report an issue: GitHub.