{"record":{"id":"b06a6bbae3c8c036","repo":"abi/screenshot-to-code","slug":"anthropic-api-key-not-found","errorCode":null,"errorMessage":"Anthropic API key not found","messagePattern":"Anthropic API key not found","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"critical","filePath":"backend/evals/core.py","lineNumber":42,"sourceCode":"    stack: Stack,\n    model: Llm,\n    input_mode: str,\n    eval_set: str | None,\n    eval_session_id: str | None,\n    input_file: str | None,\n) -> str:\n    async def send_message(\n        _: str,\n        __: str | None,\n        ___: int,\n        ____: dict[str, Any] | None = None,\n        _____: str | None = None,\n    ) -> None:\n        # Evals do not stream tool/assistant messages to a frontend.\n        return None\n\n    if model in ANTHROPIC_MODELS and not ANTHROPIC_API_KEY:\n        raise Exception(\"Anthropic API key not found\")\n    if model in GEMINI_MODELS and not GEMINI_API_KEY:\n        raise Exception(\"Gemini API key not found\")\n    if model in OPENAI_MODELS and not OPENAI_API_KEY:\n        raise Exception(\"OpenAI API key not found\")\n\n    print(f\"[EVALS] Using agent runner for model: {model.value}\")\n\n    recorder = AgentRunRecorder(\n        generation_id=(\n            f\"gen_{datetime.now().strftime('%Y%m%d_%H%M%S')}_{uuid.uuid4().hex[:8]}\"\n        ),\n        variant_index=0,\n        entry_point=\"eval\",\n        stack=str(stack),\n        input_mode=input_mode,\n        generation_type=\"create\",\n        eval_session=eval_session_id,\n        eval_set=eval_set,","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/abi/screenshot-to-code/blob/d026163f586dfa8c5c10d28c36edd59a9d3b0e88/backend/evals/core.py#L24-L60","documentation":"Exception raised by the eval runner core when model is in ANTHROPIC_MODELS but the module-level ANTHROPIC_API_KEY (loaded from env at import) is falsy. This is the evals-side duplicate of the factory guard: evals build their own agent runner with a no-op streaming callback, so they check keys before constructing it.","triggerScenarios":"Starting an eval run (e.g. /run_evals or the eval sessions UI) with a Claude model selected while ANTHROPIC_API_KEY is unset in the backend process.","commonSituations":"Eval suite launched from a shell without the env var, backend restarted before .env was complete, or evals run in CI without secrets.","solutions":["Set ANTHROPIC_API_KEY in backend/.env and restart whatever process runs the evals.","Verify the var in the exact process: the check uses the value captured at module import, so a restart is required after editing .env.","Or run the eval set against a model whose key is present."],"exampleFix":"# backend/.env\nANTHROPIC_API_KEY=sk-ant-...","handlingStrategy":"validation","validationCode":"import os\nrequired = {Llm.__members__.get(m) for m in []}  # placeholder\nif model in ANTHROPIC_MODELS and not os.environ.get(\"ANTHROPIC_API_KEY\"):\n    raise SystemExit(\"ANTHROPIC_API_KEY not set; cannot run evals on Claude models\")","typeGuard":null,"tryCatchPattern":"try:\n    await run_eval(...)\nexcept Exception as e:\n    if \"API key not found\" in str(e):\n        abort_run(\"Configure the provider key and restart the eval worker\")","preventionTips":["Provision all three provider keys in the eval worker's environment even if you eval one family.","Restart the eval worker after .env changes — keys are read at module import.","Fail eval sessions early with a clear message instead of mid-run."],"tags":["api-key","anthropic","evals","config"],"backgroundTag":null,"analyzedSha":"d026163f586dfa8c5c10d28c36edd59a9d3b0e88","analyzedAt":"2026-08-14T22:02:06.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}