{"record":{"id":"4df722cdd408b5e1","repo":"nexu-io/open-design","slug":"unsupported-web-backend-backend-r","errorCode":null,"errorMessage":"Unsupported web backend: {backend!r}","messagePattern":"Unsupported web backend: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"design-templates/last30days/scripts/lib/grounding.py","lineNumber":229,"sourceCode":"            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}\")\n    return [], {}\n\n\n# ---------------------------------------------------------------------------\n# Helpers\n# ---------------------------------------------------------------------------\n\ndef _normalize_date(value: object) -> str | None:\n    if value is None:\n        return None\n    parsed = dates.parse_date(str(value).strip())\n    if not parsed:\n        return None\n    return parsed.date().isoformat()\n\n\ndef _serper_date_param(iso_date: str) -> str:\n    \"\"\"Convert YYYY-MM-DD to MM/DD/YYYY for Serper tbs parameter.\"\"\"","sourceCodeStart":211,"sourceCodeEnd":247,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/design-templates/last30days/scripts/lib/grounding.py#L211-L247","documentation":"Final guard in web_search(): if backend is not one of auto/brave/exa/serper/parallel/none, raise ValueError(f\"Unsupported web backend: {backend!r}\"). Unlike the RuntimeError siblings this is a ValueError (programming/contract error, not a missing secret). The dispatcher normalizes 'auto' before this point, so reaching here means an explicit, unrecognized backend string was forced.","triggerScenarios":"`--web-backend bing`, `--web-backend Google`, `--web-backend \"\"` after the auto check, or any value not in the supported set passed programmatically.","commonSituations":"Typo in the backend name; case mismatch (the dispatcher does not lowercase); a stale value from old docs; passing an empty string explicitly.","solutions":["Use one of: auto, none, brave, exa, serper, parallel.","Spell it lowercase — the comparison is exact.","Prefer 'auto' to let the code choose based on which key is set."],"exampleFix":"# before\npython3.12 last30days.py --topic x --web-backend Bing\n# after\npython3.12 last30days.py --topic x --web-backend auto","handlingStrategy":"type-guard","validationCode":"SUPPORTED_BACKENDS = {'auto', 'none', 'brave', 'exa', 'serper', 'parallel'}\nif web_backend not in SUPPORTED_BACKENDS:\n    raise ValueError(f'web_backend must be one of {sorted(SUPPORTED_BACKENDS)}, got {web_backend!r}')","typeGuard":"def is_supported_backend(name: object) -> bool:\n    return isinstance(name, str) and name in {'auto','none','brave','exa','serper','parallel'}","tryCatchPattern":null,"preventionTips":["Lowercase backend names before comparison; the dispatcher is case-sensitive.","Default to 'auto' so the code selects based on available keys."],"tags":["config","python","web-search","grounding","argument-validation"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}