{"record":{"id":"d6126e6cb690e182","repo":"zylon-ai/private-gpt","slug":"brave-search-api-key-is-not-configured","errorCode":null,"errorMessage":"Brave Search API key is not configured","messagePattern":"Brave Search API key is not configured","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"private_gpt/components/web/web_search/providers/brave.py","lineNumber":81,"sourceCode":"\n        # 2. Make the request\n        response_data = await self._execute_with_retry(\n            query,\n            num_links,\n            offset,\n            result_filter,\n            safesearch,\n            freshness,\n            spellcheck,\n            language,\n        )\n\n        # 3. Parser response\n        return await asyncio.to_thread(self._parse_response, response_data)\n\n    async def validate(self) -> None:\n        if not self._api_key or not self._api_key.strip():\n            raise ValueError(\"Brave Search API key is not configured\")\n\n    def _validate_query_params(\n        self, query: str, num_links: int, offset: int\n    ) -> tuple[str, int, int]:\n        if not query or not query.strip():\n            raise ValueError(\"Search query cannot be empty\")\n\n        normalized_num_links = max(1, min(20, num_links))  # Brave allows 1-20\n        if normalized_num_links != num_links:\n            logger.warning(\n                f\"Num_links {num_links} outside valid range [1,20], clamped to {normalized_num_links}\"\n            )\n\n        if offset < 0:\n            raise ValueError(\"Offset cannot be negative\")\n\n        return query, normalized_num_links, offset\n","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/zylon-ai/private-gpt/blob/4a030776a31a901ad80b1bf4d7faa2c1a367efbb/private_gpt/components/web/web_search/providers/brave.py#L63-L99","documentation":"ValueError from BraveSearchProvider.validate(): the provider was constructed but settings.web_search.brave.api_key is None or whitespace-only. Validation runs from WebSearchService.search() → validate() before any HTTP call, so no request is wasted on a key that cannot authenticate.","triggerScenarios":"web_search.provider: brave (the default) with brave.api_key missing from settings; key set as empty string or containing only spaces; env var for the key not exported in the deployment environment.","commonSituations":"Enabling web search without signing up for a Brave Search API key; secrets managed in .env that are not passed to the container; key defined under the wrong YAML nesting (e.g. directly under web_search instead of web_search.brave).","solutions":["Set web_search.brave.api_key in settings (yaml or the corresponding env var).","Verify the env var is actually present in the process/container running private-gpt.","For local dev/tests, use provider: mock to avoid needing a key."],"exampleFix":"# settings.yaml\nweb_search:\n  enabled: true\n  provider: brave\n  brave:\n    api_key: \"BSA...\"  # was missing/blank","handlingStrategy":"validation","validationCode":"key = settings.web_search.brave.api_key\nif not key or not key.strip():\n    raise ValueError('web_search.brave.api_key missing — set it before enabling brave')","typeGuard":null,"tryCatchPattern":"try:\n    results = await search_svc.search(query)\nexcept ValueError as e:\n    if 'Brave Search API key is not configured' in str(e):\n        raise RuntimeError('Set web_search.brave.api_key in settings') from e\n    raise","preventionTips":["Run provider.validate() in a startup health check.","Use 'mock' provider for local dev and CI.","Verify secrets are mounted into the container before enabling web_search."],"tags":["configuration","api-key","brave","web-search"],"backgroundTag":null,"analyzedSha":"4a030776a31a901ad80b1bf4d7faa2c1a367efbb","analyzedAt":"2026-08-15T03:51:26.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}