{"record":{"id":"3ec9ee704670c822","repo":"nexu-io/open-design","slug":"brave-api-key-is-required-when-web-backend-brave","errorCode":null,"errorMessage":"BRAVE_API_KEY is required when web_backend='brave'","messagePattern":"BRAVE_API_KEY is required when web_backend='brave'","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"design-templates/last30days/scripts/lib/grounding.py","lineNumber":211,"sourceCode":"    config: dict,\n    backend: str = \"auto\",\n) -> tuple[list[dict], dict]:\n    \"\"\"Run web search with the specified or auto-detected backend.\"\"\"\n    if backend == \"auto\":\n        if config.get(\"BRAVE_API_KEY\"):\n            backend = \"brave\"\n        elif config.get(\"EXA_API_KEY\"):\n            backend = \"exa\"\n        elif config.get(\"SERPER_API_KEY\"):\n            backend = \"serper\"\n        elif config.get(\"PARALLEL_API_KEY\"):\n            backend = \"parallel\"\n        else:\n            return [], {}\n    if backend == \"brave\":\n        key = config.get(\"BRAVE_API_KEY\")\n        if not key:\n            raise RuntimeError(\"BRAVE_API_KEY is required when web_backend='brave'\")\n        return brave_search(query, date_range, key)\n    if backend == \"exa\":\n        key = config.get(\"EXA_API_KEY\")\n        if not key:\n            raise RuntimeError(\"EXA_API_KEY is required when web_backend='exa'\")\n        return exa_search(query, date_range, key)\n    if backend == \"serper\":\n        key = config.get(\"SERPER_API_KEY\")\n        if not key:\n            raise RuntimeError(\"SERPER_API_KEY is required when web_backend='serper'\")\n        return serper_search(query, date_range, key)\n    if backend == \"parallel\":\n        key = config.get(\"PARALLEL_API_KEY\")\n        if not key:\n            raise RuntimeError(\"PARALLEL_API_KEY is required when web_backend='parallel'\")\n        return parallel_search(query, date_range, key)\n    if backend != \"none\":\n        raise ValueError(f\"Unsupported web backend: {backend!r}\")","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/design-templates/last30days/scripts/lib/grounding.py#L193-L229","documentation":"In grounding.web_search(), when backend resolves to 'brave' (either explicitly via web_backend='brave' or auto-detected because BRAVE_API_KEY was truthy at the top of the run) but config.get('BRAVE_API_KEY') is now falsy at dispatch time, the function raises RuntimeError. The auto path would normally have set backend='brave' only when the key was present, so this explicit-backend failure typically means the user forced `--web-backend brave` (or set LAST30DAYS_WEB_BACKEND=brave) without supplying the key.","triggerScenarios":"Calling web_search(..., backend='brave') with a config dict whose BRAVE_API_KEY is missing/empty; or forcing brave via CLI/env while the key env var is unset.","commonSituations":"Setting `--web-backend brave` without exporting BRAVE_API_KEY; key present in a different env (e.g. .env not loaded); key removed between runs; CI secret not configured.","solutions":["Export BRAVE_API_KEY in the environment the script reads (and ensure config picks it up).","Or switch to a backend whose key you have: `--web-backend exa|serper|parallel`.","Or disable web grounding: `--web-backend none`.","Use `--web-backend auto` to let the code pick whichever key is present."],"exampleFix":"# before\npython3.12 last30days.py --topic x --web-backend brave   # BRAVE_API_KEY unset\n# after\nexport BRAVE_API_KEY=BSA...\npython3.12 last30days.py --topic x --web-backend brave","handlingStrategy":"validation","validationCode":"if web_backend == 'brave' and not config.get('BRAVE_API_KEY'):\n    raise RuntimeError('BRAVE_API_KEY is required when web_backend=\\'brave\\'')","typeGuard":null,"tryCatchPattern":"try:\n    items, artifact = web_search(query, date_range, config, backend='brave')\nexcept RuntimeError as e:\n    if 'BRAVE_API_KEY' in str(e):\n        # fall back to another configured backend or skip grounding\n        ...\n    raise","preventionTips":["Use `--web-backend auto` so the dispatcher picks the backend whose key is present.","Surface missing-key errors to the user clearly; do not silently fall back to no results."],"tags":["config","api-key","python","web-search","grounding"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}