{"record":{"id":"ddb3db3eccafb909","repo":"BerriAI/litellm","slug":"google-pse-api-key-is-required","errorCode":null,"errorMessage":"GOOGLE_PSE_API_KEY is required","messagePattern":"GOOGLE_PSE_API_KEY is required","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/llms/google_pse/search/transformation.py","lineNumber":176,"sourceCode":"        \"\"\"\n        if isinstance(query, list):\n            # Google PSE only supports single string queries\n            query = \" \".join(query)\n\n        # Get API credentials. The key is sent as a query param to api_base, so\n        # resolve it host-aware to avoid leaking a server-managed key to a\n        # caller-supplied host.\n        api_key = self.resolve_server_api_key(\n            caller_api_key=api_key,\n            caller_api_base=api_base,\n            key_env_vars=(\"GOOGLE_PSE_API_KEY\",),\n            base_env_var=\"GOOGLE_PSE_API_BASE\",\n            default_api_base=self.GOOGLE_PSE_API_BASE,\n        )\n        search_engine_id = search_engine_id or get_secret_str(\"GOOGLE_PSE_ENGINE_ID\")\n\n        if not api_key:\n            raise ValueError(\"GOOGLE_PSE_API_KEY is required\")\n        if not search_engine_id:\n            raise ValueError(\"GOOGLE_PSE_ENGINE_ID is required\")\n\n        request_data: Final[GooglePSESearchRequest] = {\n            \"q\": query,\n            \"cx\": search_engine_id,\n            \"key\": api_key,\n        }\n\n        # Transform unified spec parameters to Google PSE format\n        if \"max_results\" in optional_params:\n            # Google PSE supports 1-10 results per request\n            num_results: Final = min(optional_params[\"max_results\"], 10)\n            request_data[\"num\"] = num_results\n\n        if \"search_domain_filter\" in optional_params:\n            # Convert list to single domain (take first if multiple)\n            domains: Final = optional_params[\"search_domain_filter\"]","sourceCodeStart":158,"sourceCodeEnd":194,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/llms/google_pse/search/transformation.py#L158-L194","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","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."],"exampleFix":"# before: caller-controlled base + implicit server key -> resolver withholds key -> ValueError\nlitellm.web_search(provider=\"google_pse\", query=\"x\", api_base=\"https://search.internal:8443\")\n\n# after: authorize the custom base, or pass the key explicitly\nos.environ[\"GOOGLE_PSE_API_BASE\"] = \"https://search.internal:8443\"  # server key allowed for this host\n# or\nlitellm.web_search(provider=\"google_pse\", query=\"x\", api_base=\"https://search.internal:8443\", api_key=\"AIza...\")","handlingStrategy":"validation","validationCode":"import os\n\napi_key = os.getenv(\"GOOGLE_PSE_API_KEY\")\napi_base = os.getenv(\"GOOGLE_PSE_API_BASE\", \"https://www.googleapis.com\")\nif not api_key:\n    raise RuntimeError(\"GOOGLE_PSE_API_KEY missing — set it or pass api_key per request\")\n# if requests carry a custom api_base, the env base must authorize it for server keys\nif not os.getenv(\"GOOGLE_PSE_API_BASE\") and api_base != \"https://www.googleapis.com\":\n    print(\"note: custom api_base without GOOGLE_PSE_API_BASE may suppress server-key resolution\")","typeGuard":"def google_pse_request_ready(api_key: str | None, api_base: str | None, env_base: str | None) -> bool:\n    \"\"\"Key resolves only if passed explicitly or the base host is authorized via GOOGLE_PSE_API_BASE.\"\"\"\n    if api_key:\n        return True\n    import os\n    if not os.getenv(\"GOOGLE_PSE_API_KEY\"):\n        return False\n    return env_base is None or api_base in (None, env_base, \"https://www.googleapis.com\")","tryCatchPattern":"try:\n    results = litellm.web_search(provider=\"google_pse\", query=q, api_base=custom_base)\nexcept ValueError as e:\n    if \"GOOGLE_PSE_API_KEY is required\" in str(e):\n        raise RuntimeError(\n            \"Key not resolvable for this host: pass api_key explicitly or set GOOGLE_PSE_API_BASE to authorize it\"\n        ) from e\n    raise","preventionTips":["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."],"tags":["google-pse","search","api-key","configuration","host-aware-resolution"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}