{"record":{"id":"fb0f486866049b4e","repo":"headroomlabs-ai/headroom","slug":"no-llm-api-key-found-headroom-learn-needs-one-of","errorCode":null,"errorMessage":"No LLM API key found. headroom learn needs one of:\n  export ANTHROPIC_API_KEY=sk-ant-...   → uses claude-sonnet-4-6\n  export OPENAI_API_KEY=sk-...          → uses gpt-4o\n  export GEMINI_API_KEY=...             → uses gemini-flash-latest\nOr set HEADROOM_LEARN_CLI to a coding agent CLI (claude, gemini, codex).\nOr install one of those CLIs for auto-detection.\nOr specify a model directly: headroom learn --model <litellm-model-name>","messagePattern":"No LLM API key found\\. headroom learn needs one of:\n  export ANTHROPIC_API_KEY=sk-ant-\\.\\.\\.   → uses claude-sonnet-4-6\n  export OPENAI_API_KEY=sk-\\.\\.\\.          → uses gpt-4o\n  export GEMINI_API_KEY=\\.\\.\\.             → uses gemini-flash-latest\nOr set HEADROOM_LEARN_CLI to a coding agent CLI \\(claude, gemini, codex\\)\\.\nOr install one of those CLIs for auto-detection\\.\nOr specify a model directly: headroom learn --model <litellm-model-name>","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"critical","filePath":"headroom/learn/analyzer.py","lineNumber":148,"sourceCode":"    # 2. Explicit CLI selection via environment variable\n    cli_override = os.environ.get(\"HEADROOM_LEARN_CLI\")\n    if cli_override:\n        for cli_name, model, _cmd in _CLI_BACKENDS:\n            if cli_name == cli_override:\n                logger.info(\"HEADROOM_LEARN_CLI=%s — using %s CLI backend\", cli_override, cli_name)\n                return model\n        valid = \", \".join(name for name, _, _ in _CLI_BACKENDS)\n        raise ValueError(\n            f\"HEADROOM_LEARN_CLI={cli_override!r} is not a supported CLI. Valid values: {valid}\"\n        )\n\n    # 3. Auto-detect installed CLI tools\n    for cli_name, model, _cmd in _CLI_BACKENDS:\n        if shutil.which(cli_name):\n            logger.info(\"No API key found — auto-detected %s CLI as LLM backend\", cli_name)\n            return model\n\n    raise RuntimeError(\n        \"No LLM API key found. headroom learn needs one of:\\n\"\n        \"  export ANTHROPIC_API_KEY=sk-ant-...   → uses claude-sonnet-4-6\\n\"\n        \"  export OPENAI_API_KEY=sk-...          → uses gpt-4o\\n\"\n        \"  export GEMINI_API_KEY=...             → uses gemini-flash-latest\\n\"\n        \"Or set HEADROOM_LEARN_CLI to a coding agent CLI (claude, gemini, codex).\\n\"\n        \"Or install one of those CLIs for auto-detection.\\n\"\n        \"Or specify a model directly: headroom learn --model <litellm-model-name>\"\n    )\n\n\nclass SessionAnalyzer:\n    \"\"\"Analyzes session data via LLM to produce actionable recommendations.\n\n    Uses LiteLLM for provider-agnostic access to 100+ models.\n    Auto-detects the best available model from environment API keys.\n    \"\"\"\n\n    def __init__(self, model: str | None = None):","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/headroomlabs-ai/headroom/blob/322425c43bffde1ed0b64fecf3cf5951565dd82b/headroom/learn/analyzer.py#L130-L166","documentation":"Terminal failure of backend resolution for `headroom learn`: no API-key env var is set (step 1), no valid HEADROOM_LEARN_CLI override exists (step 2), and shutil.which found none of the auto-detectable coding-agent CLIs on PATH (step 3). The RuntimeError enumerates every escape hatch: three API-key env vars, the HEADROOM_LEARN_CLI override, CLI auto-detection, or --model with a LiteLLM model name.","triggerScenarios":"Running `headroom learn` in a bare environment: no ANTHROPIC_API_KEY/OPENAI_API_KEY/GEMINI_API_KEY, HEADROOM_LEARN_CLI unset or empty, and no claude/gemini/codex binaries discoverable via PATH.","commonSituations":"Fresh container/CI runner; API keys stored in a .env file that headroom doesn't load; CLI installed via a version manager (nvm, volta) whose bin dir isn't on PATH in this shell; keys set in a different shell session or systemd unit.","solutions":["Export an API key: export ANTHROPIC_API_KEY=sk-ant-... (or OPENAI_API_KEY / GEMINI_API_KEY)","Or install one of the coding-agent CLIs and ensure it's on PATH (verify with `which claude`)","Or point at a backend explicitly: export HEADROOM_LEARN_CLI=claude (valid values only)","Or bypass resolution entirely: headroom learn --model <litellm-model-name> with the matching key exported"],"exampleFix":"# before\nheadroom learn  # RuntimeError: No LLM API key found\n\n# after\nexport ANTHROPIC_API_KEY=sk-ant-...\nheadroom learn","handlingStrategy":"validation","validationCode":"import os, shutil\nok = any(os.environ.get(k) for k in ('ANTHROPIC_API_KEY', 'OPENAI_API_KEY', 'GEMINI_API_KEY')) \\\n     or os.environ.get('HEADROOM_LEARN_CLI') \\\n     or any(shutil.which(c) for c in ('claude', 'gemini', 'codex'))\nif not ok:\n    raise SystemExit('headroom learn needs an API key, HEADROOM_LEARN_CLI, an installed CLI, or --model')","typeGuard":null,"tryCatchPattern":"try:\n    subprocess.run(['headroom', 'learn'], check=True, capture_output=True)\nexcept subprocess.CalledProcessError as e:\n    if 'No LLM API key found' in (e.stderr or ''):\n        print('Set ANTHROPIC_API_KEY / OPENAI_API_KEY / GEMINI_API_KEY first')\n    raise","preventionTips":["Export the API key in the same shell/unit that runs headroom learn","Verify key presence in a preflight check (CI step or Dockerfile ENV)","For containers, bake the key via secrets and confirm `which claude` if relying on CLI auto-detection","Use --model with a matching key env var to bypass resolution entirely"],"tags":["configuration","api-key","env-var","cli","bootstrap"],"backgroundTag":null,"analyzedSha":"322425c43bffde1ed0b64fecf3cf5951565dd82b","analyzedAt":"2026-08-15T01:03:05.481Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}