BerriAI/litellm · error · ValueError

GOOGLE_PSE_API_KEY is required

Error message

GOOGLE_PSE_API_KEY is required

What it means

Raised in the google_pse search-execution path (transform_search_request equivalent) when resolve_server_api_key returns nothing for the request: no caller api_key, no GOOGLE_PSE_API_KEY env var, or the host-aware resolver refused to send a server-managed key to a caller-supplied api_base host. Functionally the same missing-key failure as error 1636, hit at request-build time instead of header-setup time; the shorter message ('is required') is the only difference.

Source

Thrown at litellm/llms/google_pse/search/transformation.py:176

        """
        if isinstance(query, list):
            # Google PSE only supports single string queries
            query = " ".join(query)

        # Get API credentials. The key is sent as a query param to api_base, so
        # resolve it host-aware to avoid leaking a server-managed key to a
        # caller-supplied host.
        api_key = self.resolve_server_api_key(
            caller_api_key=api_key,
            caller_api_base=api_base,
            key_env_vars=("GOOGLE_PSE_API_KEY",),
            base_env_var="GOOGLE_PSE_API_BASE",
            default_api_base=self.GOOGLE_PSE_API_BASE,
        )
        search_engine_id = search_engine_id or get_secret_str("GOOGLE_PSE_ENGINE_ID")

        if not api_key:
            raise ValueError("GOOGLE_PSE_API_KEY is required")
        if not search_engine_id:
            raise ValueError("GOOGLE_PSE_ENGINE_ID is required")

        request_data: Final[GooglePSESearchRequest] = {
            "q": query,
            "cx": search_engine_id,
            "key": api_key,
        }

        # Transform unified spec parameters to Google PSE format
        if "max_results" in optional_params:
            # Google PSE supports 1-10 results per request
            num_results: Final = min(optional_params["max_results"], 10)
            request_data["num"] = num_results

        if "search_domain_filter" in optional_params:
            # Convert list to single domain (take first if multiple)
            domains: Final = optional_params["search_domain_filter"]

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Set GOOGLE_PSE_API_KEY in the environment running litellm, or pass api_key on the search call.
  2. If using a custom api_base, also set GOOGLE_PSE_API_BASE to that exact host so the server key is authorized for it — or pass the key explicitly with the request.
  3. Verify the secret is actually mounted (print whether the env var exists, never its value).
  4. Enable Custom Search API on the key's Google Cloud project and restrict the key appropriately.

Example fix

# before: caller-controlled base + implicit server key -> resolver withholds key -> ValueError
litellm.web_search(provider="google_pse", query="x", api_base="https://search.internal:8443")

# after: authorize the custom base, or pass the key explicitly
os.environ["GOOGLE_PSE_API_BASE"] = "https://search.internal:8443"  # server key allowed for this host
# or
litellm.web_search(provider="google_pse", query="x", api_base="https://search.internal:8443", api_key="AIza...")
Defensive patterns

Strategy: validation

Validate before calling

import os

api_key = os.getenv("GOOGLE_PSE_API_KEY")
api_base = os.getenv("GOOGLE_PSE_API_BASE", "https://www.googleapis.com")
if not api_key:
    raise RuntimeError("GOOGLE_PSE_API_KEY missing — set it or pass api_key per request")
# if requests carry a custom api_base, the env base must authorize it for server keys
if not os.getenv("GOOGLE_PSE_API_BASE") and api_base != "https://www.googleapis.com":
    print("note: custom api_base without GOOGLE_PSE_API_BASE may suppress server-key resolution")

Type guard

def google_pse_request_ready(api_key: str | None, api_base: str | None, env_base: str | None) -> bool:
    """Key resolves only if passed explicitly or the base host is authorized via GOOGLE_PSE_API_BASE."""
    if api_key:
        return True
    import os
    if not os.getenv("GOOGLE_PSE_API_KEY"):
        return False
    return env_base is None or api_base in (None, env_base, "https://www.googleapis.com")

Try / catch

try:
    results = litellm.web_search(provider="google_pse", query=q, api_base=custom_base)
except ValueError as e:
    if "GOOGLE_PSE_API_KEY is required" in str(e):
        raise RuntimeError(
            "Key not resolvable for this host: pass api_key explicitly or set GOOGLE_PSE_API_BASE to authorize it"
        ) from e
    raise

Prevention

When it happens

Trigger: Executing a google_pse search request where api_key was not supplied per-call and no env key exists; or api_base points to a host different from the default (https://www.googleapis.com)/GOOGLE_PSE_API_BASE while relying on the server-side env key, so the resolver withholds the key for safety and it resolves as missing.

Common situations: Proxy deployments where callers send a custom api_base expecting the server to attach its key — the host-aware resolution blocks that; missing secrets in Kubernetes ConfigMaps; env vars named slightly differently (e.g. GITHUB-style naming copied into search config).

Related errors


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/ddb3db3eccafb909. Report an issue: GitHub.