{"record":{"id":"4a4c600a0027e852","repo":"danny-avila/LibreChat","slug":"request-failed-with-status-response-status-j","errorCode":null,"errorMessage":"Request failed with status ${response.status}: ${json.error.message}","messagePattern":"Request failed with status (.+?): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"api/app/clients/tools/structured/GoogleSearch.js","lineNumber":72,"sourceCode":"\n  async _call(input) {\n    const { query, max_results = 5 } = input;\n\n    const response = await fetch(\n      `https://www.googleapis.com/customsearch/v1?key=${this.apiKey}&cx=${\n        this.searchEngineId\n      }&q=${encodeURIComponent(query)}&num=${max_results}`,\n      {\n        method: 'GET',\n        headers: {\n          'Content-Type': 'application/json',\n        },\n      },\n    );\n\n    const json = await response.json();\n    if (!response.ok) {\n      throw new Error(`Request failed with status ${response.status}: ${json.error.message}`);\n    }\n\n    return JSON.stringify(json);\n  }\n}\n\nmodule.exports = GoogleSearchResults;\n","sourceCodeStart":54,"sourceCodeEnd":80,"githubUrl":"https://github.com/danny-avila/LibreChat/blob/5ff282f9006c436e561de1afd39a481bea1ef0d8/api/app/clients/tools/structured/GoogleSearch.js#L54-L80","documentation":"Thrown by GoogleSearch._call() when the fetch to the Custom Search JSON API returns a non-2xx status. It surfaces `response.status` and `json.error.message` from Google's error body. Common upstream causes: invalid/expired API key, disabled Custom Search API, exhausted daily quota (100/day free), invalid/missing cx (CSE ID), or a malformed query. Note: if Google returns a non-OK body without an `error.message` field, this line will instead throw a TypeError reading `json.error.message` — a latent fragility.","triggerScenarios":"Any `_call()` invocation against https://www.googleapis.com/customsearch/v1?key=...&cx=...&q=... where the response status is not ok — e.g., 403 (API key invalid / API disabled), 429 (quota exceeded), 400 (bad cx), or 503.","commonSituations":"Quota hit after the free 100 queries/day; API key was rotated in the console but not in .env; the Custom Search Engine was deleted or its ID changed; the project lacks the Custom Search API enabled; transient Google 5xx during heavy load; non-ASCII query that wasn't encoded (note the call already encodeURIComponent's q).","solutions":["Read the surfaced status and json.error.message — 403 → rotate/fix the API key and enable the API; 429 → raise quota or wait; 400 → verify GOOGLE_CSE_ID.","Verify billing/quota in Google Cloud Console > APIs & Services > Custom Search API.","Confirm the API key has the Custom Search API enabled and is not restricted in a way that blocks it.","Wrap _call() in try/catch and degrade gracefully (return a 'search unavailable' message to the agent).","If you hit the TypeError variant, patch the line to guard `json?.error?.message`."],"exampleFix":"// before — upstream 429 surfaces raw\nconst out = await searchTool.invoke('latest news');\n\n// caller-side guard\ntry {\n  const out = await searchTool.invoke('latest news');\n} catch (e) {\n  if (/status 429/.test(e.message)) return 'Search quota exceeded, try later.';\n  throw e;\n}\n\n// library hardening (optional)\n//   throw new Error(`Request failed ${response.status}: ${json?.error?.message ?? response.statusText}`);","handlingStrategy":"try-catch","validationCode":"function isLikelyValidGoogleSearchCall(args) {\n  return Boolean(args?.query) && Boolean(process.env.GOOGLE_SEARCH_API_KEY) && Boolean(process.env.GOOGLE_CSE_ID);\n}","typeGuard":"function isQuotaError(e) {\n  return /status 429/.test(e?.message || '');\n}","tryCatchPattern":"try {\n  const out = await searchTool.invoke(query);\n} catch (e) {\n  const msg = e.message || '';\n  if (/status 403/.test(msg)) return 'Google Search API key invalid or API disabled.';\n  if (/status 429/.test(msg)) return 'Search quota exceeded for today.';\n  if (/status 400/.test(msg)) return 'Invalid Custom Search Engine ID.';\n  throw e;\n}","preventionTips":["Monitor daily Custom Search API usage; upgrade billing before hitting the 100/day free cap.","Restrict the API key to the Custom Search API in Google Cloud to limit blast radius.","Guard the throw site with `json?.error?.message` to avoid the TypeError on odd error bodies.","Cache search results for repeated queries to cut quota use."],"tags":["google-search","network","upstream","quota","api-error"],"backgroundTag":null,"analyzedSha":"5ff282f9006c436e561de1afd39a481bea1ef0d8","analyzedAt":"2026-08-12T21:38:08.145Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}