nexu-io/open-design · error · RuntimeError
BRAVE_API_KEY is required when web_backend='brave'
Error message
BRAVE_API_KEY is required when web_backend='brave'
What it means
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.
Source
Thrown at design-templates/last30days/scripts/lib/grounding.py:211
config: dict,
backend: str = "auto",
) -> tuple[list[dict], dict]:
"""Run web search with the specified or auto-detected backend."""
if backend == "auto":
if config.get("BRAVE_API_KEY"):
backend = "brave"
elif config.get("EXA_API_KEY"):
backend = "exa"
elif config.get("SERPER_API_KEY"):
backend = "serper"
elif config.get("PARALLEL_API_KEY"):
backend = "parallel"
else:
return [], {}
if backend == "brave":
key = config.get("BRAVE_API_KEY")
if not key:
raise RuntimeError("BRAVE_API_KEY is required when web_backend='brave'")
return brave_search(query, date_range, key)
if backend == "exa":
key = config.get("EXA_API_KEY")
if not key:
raise RuntimeError("EXA_API_KEY is required when web_backend='exa'")
return exa_search(query, date_range, key)
if backend == "serper":
key = config.get("SERPER_API_KEY")
if not key:
raise RuntimeError("SERPER_API_KEY is required when web_backend='serper'")
return serper_search(query, date_range, key)
if backend == "parallel":
key = config.get("PARALLEL_API_KEY")
if not key:
raise RuntimeError("PARALLEL_API_KEY is required when web_backend='parallel'")
return parallel_search(query, date_range, key)
if backend != "none":
raise ValueError(f"Unsupported web backend: {backend!r}")View on GitHub (pinned to 5be4028344)
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.
Example fix
# before python3.12 last30days.py --topic x --web-backend brave # BRAVE_API_KEY unset # after export BRAVE_API_KEY=BSA... python3.12 last30days.py --topic x --web-backend brave
Defensive patterns
Strategy: validation
Validate before calling
if web_backend == 'brave' and not config.get('BRAVE_API_KEY'):
raise RuntimeError('BRAVE_API_KEY is required when web_backend=\'brave\'') Try / catch
try:
items, artifact = web_search(query, date_range, config, backend='brave')
except RuntimeError as e:
if 'BRAVE_API_KEY' in str(e):
# fall back to another configured backend or skip grounding
...
raise Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- EXA_API_KEY is required when web_backend='exa'
- SERPER_API_KEY is required when web_backend='serper'
- PARALLEL_API_KEY is required when web_backend='parallel'
- Unsupported web backend: {backend!r}
- No sources are available for this run.
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/3ec9ee704670c822.
Report an issue: GitHub.