{"record":{"id":"d54484229cf08300","repo":"musistudio/claude-code-router","slug":"gateway-serper-web-search-api-key-is-not-configu","errorCode":null,"errorMessage":"[gateway] Serper web search API key is not configured.","messagePattern":"\\[gateway\\] Serper web search API key is not configured\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/core/src/gateway/features/hosted-web-search/discovery.ts","lineNumber":593,"sourceCode":"  const cx = searchEnv(input, \"GOOGLE_SEARCH_CX\");\n  if (!apiKey || !cx) {\n    console.warn(\"[gateway] Google CSE web search API key or engine ID is not configured.\");\n    return [];\n  }\n  const url = new URL(searchEnv(input, \"GOOGLE_SEARCH_ENDPOINT\") || \"https://www.googleapis.com/customsearch/v1\");\n  url.searchParams.set(\"key\", apiKey);\n  url.searchParams.set(\"cx\", cx);\n  url.searchParams.set(\"q\", input.query);\n  url.searchParams.set(\"num\", String(Math.min(input.count, 10)));\n  const raw = await fetchJson(url.toString(), { signal: AbortSignal.timeout(input.timeoutMs) });\n  const items = isRecord(raw) && Array.isArray(raw.items) ? raw.items : [];\n  return items.map((item) => webSearchResult(item, \"title\", \"link\", \"snippet\")).filter(isWebSearchProviderResult);\n}\n\nasync function searchSerper(input: WebSearchProviderInput): Promise<WebSearchProviderResult[]> {\n  const apiKey = searchEnv(input, \"SERPER_API_KEY\");\n  if (!apiKey) {\n    console.warn(\"[gateway] Serper web search API key is not configured.\");\n    return [];\n  }\n  const raw = await fetchJson(searchEnv(input, \"SERPER_SEARCH_ENDPOINT\") || \"https://google.serper.dev/search\", {\n    body: JSON.stringify({ num: input.count, q: input.query }),\n    headers: {\n      \"content-type\": \"application/json\",\n      \"x-api-key\": apiKey\n    },\n    method: \"POST\",\n    signal: AbortSignal.timeout(input.timeoutMs)\n  });\n  const items = isRecord(raw) && Array.isArray(raw.organic) ? raw.organic : [];\n  return items.map((item) => webSearchResult(item, \"title\", \"link\", \"snippet\")).filter(isWebSearchProviderResult);\n}\n\nasync function searchSerpApi(input: WebSearchProviderInput): Promise<WebSearchProviderResult[]> {\n  const apiKey = searchEnv(input, \"SERPAPI_API_KEY\");\n  if (!apiKey) {","sourceCodeStart":575,"sourceCodeEnd":611,"githubUrl":"https://github.com/musistudio/claude-code-router/blob/99f24806c6a2c660b16e53e95211c517448a6c90/packages/core/src/gateway/features/hosted-web-search/discovery.ts#L575-L611","documentation":"The Serper.dev web search provider was selected, but SERPER_API_KEY is not configured in the resolved environment. The provider returns an empty result list, so searches silently produce nothing.","triggerScenarios":"Setting web search provider to \"serper\" without SERPER_API_KEY; the key not being propagated to the gateway's runtime environment (container, systemd, CI).","commonSituations":"Key obtained from serper.dev but stored in a shell rc file not sourced by the service; env var named differently (SERPER_KEY); stale deployment secrets.","solutions":["Set SERPER_API_KEY to your serper.dev API key in the gateway environment","Confirm the variable reaches the process (check service definition or container env)","Restart the gateway"],"exampleFix":"# before\nWEB_SEARCH_PROVIDER=serper\n\n# after\nSERPER_API_KEY=<serper-key>\nWEB_SEARCH_PROVIDER=serper","handlingStrategy":"validation","validationCode":"if (!process.env.SERPER_API_KEY) throw new Error(\"SERPER_API_KEY required for serper provider\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate keys at startup","Document required vars per provider in deployment READMEs","Alert when searches return 0 results repeatedly"],"tags":["web-search","serper","env-var","api-key"],"backgroundTag":"missing-env-var","analyzedSha":"99f24806c6a2c660b16e53e95211c517448a6c90","analyzedAt":"2026-08-27T04:11:01.184Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}