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
- Set GOOGLE_PSE_API_KEY in the environment running litellm, or pass api_key on the search call.
- 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.
- Verify the secret is actually mounted (print whether the env var exists, never its value).
- 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
- Pass api_key explicitly whenever routing to a custom api_base.
- Set GOOGLE_PSE_API_BASE to the exact host server keys may be sent to.
- Understand host-aware resolution: server-managed keys never go to caller-supplied hosts.
- Keep a config pre-flight asserting the key env var is non-empty.
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
- GOOGLE_PSE_API_KEY is not set. Set `GOOGLE_PSE_API_KEY` envi
- GOOGLE_PSE_ENGINE_ID is not set. Set `GOOGLE_PSE_ENGINE_ID`
- GOOGLE_PSE_ENGINE_ID is required
- APISERPENT_API_KEY is not set. Set `APISERPENT_API_KEY` envi
- Azure OpenAI client is not initialized. Make sure api_key is
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/ddb3db3eccafb909.
Report an issue: GitHub.