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

  1. Export BRAVE_API_KEY in the environment the script reads (and ensure config picks it up).
  2. Or switch to a backend whose key you have: `--web-backend exa|serper|parallel`.
  3. Or disable web grounding: `--web-backend none`.
  4. 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

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


AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12). Data as JSON: /api/errors/3ec9ee704670c822. Report an issue: GitHub.