{"record":{"id":"01697da2fcb0e8e2","repo":"musistudio/claude-code-router","slug":"gateway-serpapi-web-search-api-key-is-not-config","errorCode":null,"errorMessage":"[gateway] SerpAPI web search API key is not configured.","messagePattern":"\\[gateway\\] SerpAPI 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":612,"sourceCode":"    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) {\n    console.warn(\"[gateway] SerpAPI web search API key is not configured.\");\n    return [];\n  }\n  const url = new URL(searchEnv(input, \"SERPAPI_SEARCH_ENDPOINT\") || \"https://serpapi.com/search.json\");\n  url.searchParams.set(\"api_key\", apiKey);\n  url.searchParams.set(\"engine\", \"google\");\n  url.searchParams.set(\"q\", input.query);\n  url.searchParams.set(\"num\", String(input.count));\n  const raw = await fetchJson(url.toString(), { signal: AbortSignal.timeout(input.timeoutMs) });\n  const items = isRecord(raw) && Array.isArray(raw.organic_results) ? raw.organic_results : [];\n  return items.map((item) => webSearchResult(item, \"title\", \"link\", \"snippet\")).filter(isWebSearchProviderResult);\n}\n\nasync function searchTavily(input: WebSearchProviderInput): Promise<WebSearchProviderResult[]> {\n  const apiKey = searchEnv(input, \"TAVILY_API_KEY\");\n  if (!apiKey) {\n    console.warn(\"[gateway] Tavily web search API key is not configured.\");\n    return [];\n  }","sourceCodeStart":594,"sourceCodeEnd":630,"githubUrl":"https://github.com/musistudio/claude-code-router/blob/99f24806c6a2c660b16e53e95211c517448a6c90/packages/core/src/gateway/features/hosted-web-search/discovery.ts#L594-L630","documentation":"The SerpAPI web search provider was selected, but SERPAPI_API_KEY is missing from the resolved environment. The provider returns empty results rather than failing the request.","triggerScenarios":"Configuring web search provider to \"serpapi\" without SERPAPI_API_KEY; key set only in a local .env not loaded in production.","commonSituations":"Signing up at serpapi.com but never exporting the key; containerized gateway missing the secret; key rotation leaving the env stale.","solutions":["Set SERPAPI_API_KEY in the gateway's runtime environment","Verify with a quick curl 'https://serpapi.com/search.json?api_key=...&q=test' that the key works","Restart the gateway process"],"exampleFix":"# before\nWEB_SEARCH_PROVIDER=serpapi\n\n# after\nSERPAPI_API_KEY=<serpapi-key>\nWEB_SEARCH_PROVIDER=serpapi","handlingStrategy":"validation","validationCode":"if (!process.env.SERPAPI_API_KEY) throw new Error(\"SERPAPI_API_KEY required for serpapi provider\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate keys at startup","Sync secrets into the service environment via deployment tooling","Test one search after config changes"],"tags":["web-search","serpapi","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"}