{"record":{"id":"46cf29f0d1bff701","repo":"virattt/ai-hedge-fund","slug":"env-var-not-found-set-it-in-your-env-to-use-p","errorCode":null,"errorMessage":"{env_var} not found. Set it in your .env to use {provider} models.","messagePattern":"(.+?) not found\\. Set it in your \\.env to use (.+?) models\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"hedge_fund/llm/client.py","lineNumber":184,"sourceCode":"    if isinstance(content, list):\n        parts = []\n        for block in content:\n            if isinstance(block, str):\n                parts.append(block)\n            elif isinstance(block, dict) and block.get(\"type\") == \"text\":\n                parts.append(block.get(\"text\", \"\"))\n        return sep.join(parts)\n    return \"\" if content is None else str(content)\n\n\ndef _require_key(provider: str) -> str:\n    \"\"\"The provider's API key, or a failure that names the variable to set.\"\"\"\n    env_var = env_var_for(provider)\n    # Kimi accepts either name; v1 reads MOONSHOT_API_KEY first.\n    key = (os.getenv(\"MOONSHOT_API_KEY\") if provider == \"Kimi\" else None)\n    key = key or (os.getenv(env_var) if env_var else None)\n    if not key:\n        raise ValueError(\n            f\"{env_var} not found. Set it in your .env to use {provider} models.\"\n        )\n    return key\n\n\ndef extract_json(text: str) -> dict:\n    \"\"\"Pull the first JSON object out of an LLM response.\n\n    Tries: ```json fence -> whole string -> first balanced {...} block.\n    Raises LLMParseError if nothing parses.\n    \"\"\"\n    fence = re.search(r\"```(?:json)?\\s*(\\{.*?\\})\\s*```\", text, re.DOTALL)\n    if fence:\n        try:\n            return json.loads(fence.group(1))\n        except json.JSONDecodeError:\n            pass\n","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/virattt/ai-hedge-fund/blob/eff8a7320fcf0b473b135690fa1a5b0d9b022a83/hedge_fund/llm/client.py#L166-L202","documentation":"Raised by _require_key (hedge_fund/llm/client.py:184) when the provider's API key environment variable is unset or empty. The error deliberately names the exact variable (ANTHROPIC_API_KEY, OPENAI_API_KEY, XAI_API_KEY, DEEPSEEK_API_KEY, GOOGLE_API_KEY, KIMI_API_KEY — Kimi also accepts MOONSHOT_API_KEY) because that is the only actionable item for the user.","triggerScenarios":"Calling make_llm() (directly or via an LLM-agent signal) with no .env loaded: no ANTHROPIC_API_KEY when defaulting to claude-sonnet-5; selecting a DeepSeek or Google model in the TUI without its key set; key present but empty string. Note Kimi has a two-name fallback (MOONSHOT_API_KEY then KIMI_API_KEY); all other providers check exactly one variable.","commonSituations":"Fresh clone without copying .env.example; .env file exists but the process wasn't started in a directory where it's loaded, or the key line is commented out; CI runner missing the secret; typo in the variable name (e.g. ANTHROPIC_KEY).","solutions":["Add the exact variable named in the message to your .env (e.g. ANTHROPIC_API_KEY=sk-ant-...) and restart the process so it's reloaded.","If the .env exists but isn't picked up, verify it's on the loader's path (cwd / dotenv config) or export the variable in the shell.","For Kimi specifically, either KIMI_API_KEY or MOONSHOT_API_KEY works — set whichever you have."],"exampleFix":"# before\n# .env missing key -> ValueError: ANTHROPIC_API_KEY not found. Set it in your .env to use Anthropic models.\n\n# after\n# .env\nANTHROPIC_API_KEY=sk-ant-your-key-here","handlingStrategy":"validation","validationCode":"from hedge_fund.llm.registry import PROVIDER_ENV_VARS, provider_for\n\ndef key_is_set(model_id: str) -> bool:\n    provider = provider_for(model_id) or \"Anthropic\"\n    env_var = PROVIDER_ENV_VARS[provider]\n    import os\n    if provider == \"Kimi\":\n        return bool(os.getenv(\"KIMI_API_KEY\") or os.getenv(\"MOONSHOT_API_KEY\"))\n    return bool(os.getenv(env_var))","typeGuard":"import os\nfrom hedge_fund.llm.registry import PROVIDER_ENV_VARS\n\ndef provider_key_present(provider: str) -> bool:\n    env_var = PROVIDER_ENV_VARS.get(provider)\n    if env_var is None:\n        return False\n    if provider == \"Kimi\":\n        return bool(os.getenv(\"MOONSHOT_API_KEY\") or os.getenv(env_var))\n    return bool(os.getenv(env_var))","tryCatchPattern":"try:\n    chat = make_llm()\nexcept ValueError as e:\n    if \"not found. Set it in your .env\" in str(e):\n        raise SystemExit(str(e)) from e  # message already names the variable\n    raise","preventionTips":["At startup, check the key for the configured provider and fail fast with the variable name.","Copy .env.example to .env on fresh clones before running anything LLM-backed.","In CI, inject provider keys as secrets and assert make_llm() constructs cleanly in a smoke job."],"tags":["llm","api-key","env","configuration"],"backgroundTag":null,"analyzedSha":"eff8a7320fcf0b473b135690fa1a5b0d9b022a83","analyzedAt":"2026-08-15T00:22:46.567Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}