{"record":{"id":"8f7d450d0dc98270","repo":"Kuberwastaken/claurst","slug":"no-api-key-found-options-set-anthropic-api-key","errorCode":null,"errorMessage":"No API key found. Options:\n- Set ANTHROPIC_API_KEY for Anthropic\n- Set OPENAI_API_KEY for OpenAI\n- Set GOOGLE_API_KEY for Google Gemini\n- Set GROQ_API_KEY for Groq (fast, free tier available)\n- Run `claurst --provider ollama` for local models (no key needed)\n- Run `claurst auth login` for Anthropic OAuth","messagePattern":"No API key found\\. Options:\n- Set ANTHROPIC_API_KEY for Anthropic\n- Set OPENAI_API_KEY for OpenAI\n- Set GOOGLE_API_KEY for Google Gemini\n- Set GROQ_API_KEY for Groq \\(fast, free tier available\\)\n- Run `claurst --provider ollama` for local models \\(no key needed\\)\n- Run `claurst auth login` for Anthropic OAuth","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-rust/crates/cli/src/main.rs","lineNumber":617,"sourceCode":"    }\n    if let Some(ref append) = config.append_system_prompt {\n        system_parts.push(append.clone());\n    }\n    let system_prompt = system_parts.join(\"\\n\\n\");\n\n    // Initialize API client.\n    // Try config/env first; fall back to saved OAuth tokens.\n    // If no Anthropic credentials are found, check whether any other provider is\n    // configured (OpenAI, Google, Ollama, Groq, etc.) — if so, proceed without\n    // requiring Anthropic auth. Only launch the OAuth flow when Anthropic is\n    // explicitly the intended provider and no key exists at all.\n    let active_provider = config.selected_provider_id();\n    let (api_key, use_bearer_auth) = if active_provider == \"anthropic\" {\n        match config.resolve_anthropic_auth_async().await {\n            Some(auth) => auth,\n            None => {\n                if is_headless {\n                    anyhow::bail!(\n                        \"No API key found. Options:\\n\\\n                         - Set ANTHROPIC_API_KEY for Anthropic\\n\\\n                         - Set OPENAI_API_KEY for OpenAI\\n\\\n                         - Set GOOGLE_API_KEY for Google Gemini\\n\\\n                         - Set GROQ_API_KEY for Groq (fast, free tier available)\\n\\\n                         - Run `claurst --provider ollama` for local models (no key needed)\\n\\\n                         - Run `claurst auth login` for Anthropic OAuth\"\n                    );\n                } else {\n                    (String::new(), false)\n                }\n            }\n        }\n    } else {\n        (String::new(), false)\n    };\n\n    // Apply the user-configured request timeout (issue #175) before building any","sourceCodeStart":599,"sourceCodeEnd":635,"githubUrl":"https://github.com/Kuberwastaken/claurst/blob/b0637c97ec34144387cbf2f74f65df6d16a6cef1/src-rust/crates/cli/src/main.rs#L599-L635","documentation":"At startup, when the active provider is Anthropic, main resolves credentials via resolve_anthropic_auth_async (API key from config/env, or saved OAuth tokens). In headless (`--print`) mode there is no interactive prompt/OAuth flow available, so if no credentials resolve at all the program bails with a message listing every supported way to supply a key.","triggerScenarios":"Running claurst in headless mode (`--print`, or a non-TTY environment) with the active provider resolving to \"anthropic\" while: ANTHROPIC_API_KEY is unset, no key is stored in settings/config, and no Anthropic OAuth tokens exist in the auth store. resolve_anthropic_auth_async returns None and is_headless is true.","commonSituations":"Fresh machine or CI container without exported credentials; ANTHROPIC_API_KEY defined only in an interactive shell profile but not in the cron/CI environment; switching back to the default Anthropic provider after previously using another provider; running via a wrapper (editor plugin, script) that drops environment variables.","solutions":["Export a key: `export ANTHROPIC_API_KEY=sk-ant-...` (or set OPENAI_API_KEY / GOOGLE_API_KEY / GROQ_API_KEY and select that provider)","Run `claurst auth login` interactively once to store Anthropic OAuth tokens; headless runs will then resolve them","For CI/headless without any key, use the local provider: `claurst --provider ollama --print \"...\"` (no key required)","Run `claurst --provider <other> --print \"...\"` if you have a key for a non-Anthropic provider but none for Anthropic","Check that the env var actually reaches the process (`env | grep API_KEY` inside the same context CI/cron uses) and that ~/.claurst auth store is populated on this machine/user"],"exampleFix":"// before: headless run with no credentials in scope\nci-job: claurst --print \"summarize\"  // -> No API key found\n\n// after: provide credentials to the headless environment\nci-job:\n  env:\n    ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}\n  script: claurst --print \"summarize\"","handlingStrategy":"validation","validationCode":"# Verify a credential source exists before a headless run\n[ -n \"$ANTHROPIC_API_KEY\" ] || [ -f \"$HOME/.claurst/auth.json\" ] \\\n  || { echo \"No Anthropic credentials for headless run\"; exit 1; }","typeGuard":null,"tryCatchPattern":"# Fall back to a keyless local provider when no key is present\nif ! claurst --print \"task\" 2>/dev/null; then\n  claurst --provider ollama --print \"task\"\nfi","preventionTips":["Set ANTHROPIC_API_KEY in the environment that actually runs the process (CI env secrets, cron, systemd), not only the interactive shell","Run `claurst auth login` once per machine/user so OAuth tokens backstop missing keys","Use --provider ollama for keyless headless/local work","Smoke-test headless mode (`claurst --print \"hi\"`) in CI before real jobs"],"tags":["api-key","authentication","configuration","headless"],"backgroundTag":"missing-api-key","analyzedSha":"b0637c97ec34144387cbf2f74f65df6d16a6cef1","analyzedAt":"2026-09-10T00:24:58.650Z","contentChangedAt":"2026-09-10T00:24:58.650Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}