zylon-ai/private-gpt · error · ValueError

Search query cannot be empty

Error message

Search query cannot be empty

What it means

ValueError from BraveSearchProvider._validate_query_params: the query passed to search()/make_query is None, empty, or only whitespace. This is client-side validation before the Brave API is called, because Brave would reject a blank q parameter anyway.

Source

Thrown at private_gpt/components/web/web_search/providers/brave.py:87

            result_filter,
            safesearch,
            freshness,
            spellcheck,
            language,
        )

        # 3. Parser response
        return await asyncio.to_thread(self._parse_response, response_data)

    async def validate(self) -> None:
        if not self._api_key or not self._api_key.strip():
            raise ValueError("Brave Search API key is not configured")

    def _validate_query_params(
        self, query: str, num_links: int, offset: int
    ) -> tuple[str, int, int]:
        if not query or not query.strip():
            raise ValueError("Search query cannot be empty")

        normalized_num_links = max(1, min(20, num_links))  # Brave allows 1-20
        if normalized_num_links != num_links:
            logger.warning(
                f"Num_links {num_links} outside valid range [1,20], clamped to {normalized_num_links}"
            )

        if offset < 0:
            raise ValueError("Offset cannot be negative")

        return query, normalized_num_links, offset

    async def _execute_http_request(
        self,
        query: str,
        num_links: int,
        offset: int,
        result_filter: str,

View on GitHub (pinned to 4a030776a3)

Solutions

  1. Guard at the call site: skip the search when the query is blank instead of calling the API.
  2. Trim and validate user/model-provided query strings before dispatch.
  3. If the query legitimately came back empty from an LLM tool call, fix the tool schema to require a non-empty string.

Example fix

# before
results = await web_search.search(query)

# after
if not query or not query.strip():
    return []
results = await web_search.search(query.strip())
Defensive patterns

Strategy: validation

Validate before calling

def valid_search_query(q: str | None) -> bool:
    return bool(q and q.strip())

if not valid_search_query(query):
    return []  # skip search instead of raising

Type guard

def is_empty_query_error(exc: BaseException) -> bool:
    return isinstance(exc, ValueError) and str(exc) == 'Search query cannot be empty'

Try / catch

try:
    results = await provider.make_query(query, num_links)
except ValueError as e:
    if str(e) == 'Search query cannot be empty':
        return []
    raise

Prevention

When it happens

Trigger: Calling WebSearchService.search('') or search(' '); a caller building the query from user input that arrived empty (blank chat turn, stripped template); passing query=None through **kwargs paths that skip earlier null checks.

Common situations: LLM tool-calling flows where the model emits an empty query argument; frontends forwarding a search box with no text; whitespace-only strings after trimming user input.

Related errors


AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15). Data as JSON: /api/errors/dac84f90af859490. Report an issue: GitHub.