microsoft/semantic-kernel · error · ServiceInvalidRequestError

Failed to get search results.

Error message

Failed to get search results.

What it means

_inner_search issues an async GET to the Google Custom Search API and calls response.raise_for_status(). Any HTTP 4xx/5xx becomes an httpx.HTTPStatusError, which is logged and re-raised as ServiceInvalidRequestError('Failed to get search results.'). The original HTTPStatusError is preserved in __cause__ so the status code and body are recoverable.

Source

Thrown at python/semantic_kernel/connectors/google_search.py:273

    async def _inner_search(self, query: str, options: SearchOptions) -> GoogleSearchResponse:
        self._validate_options(options)

        logger.info(
            f"Received request for google web search with \
                params:\nnum_results: {options.top}\noffset: {options.skip}"
        )

        full_url = f"{CUSTOM_SEARCH_URL}{self._build_query(query, options)}"
        headers = {"user_agent": SEMANTIC_KERNEL_USER_AGENT}
        try:
            async with AsyncClient(timeout=5) as client:
                response = await client.get(full_url, headers=headers)
                response.raise_for_status()
                return GoogleSearchResponse.model_validate_json(response.text)
        except HTTPStatusError as ex:
            logger.error(f"Failed to get search results: {ex}")
            raise ServiceInvalidRequestError("Failed to get search results.") from ex
        except RequestError as ex:
            logger.error(f"Client error occurred: {ex}")
            raise ServiceInvalidRequestError("A client error occurred while getting search results.") from ex
        except Exception as ex:
            logger.error(f"An unexpected error occurred: {ex}")
            raise ServiceInvalidRequestError("An unexpected error occurred while getting search results.") from ex

    def _validate_options(self, options: SearchOptions) -> None:
        if options.top > 10:
            raise ServiceInvalidRequestError("count value must be less than or equal to 10.")

    def _parse_filter_lambda(self, filter_lambda: Callable | str) -> list[dict[str, str]]:
        """Parse a string lambda or string expression into a list of {field: value} dicts using AST."""
        expr = filter_lambda if isinstance(filter_lambda, str) else getsource(filter_lambda).strip()
        tree = ast.parse(expr, mode="eval")
        node = tree.body
        visitor = SearchLambdaVisitor(valid_parameters=QUERY_PARAMETERS)
        visitor.visit(node)

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Inspect ex.__cause__.response.status_code and .text to identify the exact HTTP failure.
  2. Verify the API key and cx (engine_id) are valid and enabled in the Google Cloud / Programmable Search console.
  3. For 429, back off and retry with exponential backoff; enable billing or raise quota.
  4. For 5xx, retry a limited number of times before surfacing the error to the user.

Example fix

# before
results = await google.search('skates')  # 403/429 -> [1303]

# after
from semantic_kernel.exceptions import ServiceInvalidRequestError
try:
    results = await google.search('skates')
except ServiceInvalidRequestError as ex:
    resp = ex.__cause__.response
    if resp.status_code in (429, 500, 502, 503):
        await asyncio.sleep(2 ** attempt)
        results = await google.search('skates')
    else:
        raise
Defensive patterns

Strategy: try-catch

Try / catch

from semantic_kernel.exceptions import ServiceInvalidRequestError

RETRYABLE = {429, 500, 502, 503, 504}
for attempt in range(5):
    try:
        results = await google.search(query, top=top)
        break
    except ServiceInvalidRequestError as ex:
        cause = ex.__cause__
        status = getattr(getattr(cause, 'response', None), 'status_code', None)
        if status in RETRYABLE and attempt < 4:
            await asyncio.sleep(2 ** attempt)
            continue
        raise

Prevention

When it happens

Trigger: HTTP 403 (invalid/disabled API key), 400 (bad cx / engine_id or malformed query params), 429 (quota/rate limit exceeded), or 5xx (Google server error) returned by https://www.googleapis.com/customsearch/v1.

Common situations: Wrong or revoked API key; incorrect search_engine_id (cx); daily quota exhausted on the free tier; billing disabled; transient Google 5xx during outages.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/051c7fb87ca8abfe. Report an issue: GitHub.