danny-avila/LibreChat · error · Error
Request failed with status ${response.status}: ${json.error.
Error message
Request failed with status ${response.status}: ${json.error.message} What it means
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.
Source
Thrown at api/app/clients/tools/structured/GoogleSearch.js:72
async _call(input) {
const { query, max_results = 5 } = input;
const response = await fetch(
`https://www.googleapis.com/customsearch/v1?key=${this.apiKey}&cx=${
this.searchEngineId
}&q=${encodeURIComponent(query)}&num=${max_results}`,
{
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
},
);
const json = await response.json();
if (!response.ok) {
throw new Error(`Request failed with status ${response.status}: ${json.error.message}`);
}
return JSON.stringify(json);
}
}
module.exports = GoogleSearchResults;
View on GitHub (pinned to 5ff282f900)
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`.
Example fix
// before — upstream 429 surfaces raw
const out = await searchTool.invoke('latest news');
// caller-side guard
try {
const out = await searchTool.invoke('latest news');
} catch (e) {
if (/status 429/.test(e.message)) return 'Search quota exceeded, try later.';
throw e;
}
// library hardening (optional)
// throw new Error(`Request failed ${response.status}: ${json?.error?.message ?? response.statusText}`); Defensive patterns
Strategy: try-catch
Validate before calling
function isLikelyValidGoogleSearchCall(args) {
return Boolean(args?.query) && Boolean(process.env.GOOGLE_SEARCH_API_KEY) && Boolean(process.env.GOOGLE_CSE_ID);
} Type guard
function isQuotaError(e) {
return /status 429/.test(e?.message || '');
} Try / catch
try {
const out = await searchTool.invoke(query);
} catch (e) {
const msg = e.message || '';
if (/status 403/.test(msg)) return 'Google Search API key invalid or API disabled.';
if (/status 429/.test(msg)) return 'Search quota exceeded for today.';
if (/status 400/.test(msg)) return 'Invalid Custom Search Engine ID.';
throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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).
Related errors
- Invalid response from the STT API
- Failed to fetch image from URL. Status: ${response.status}
- Missing ${this.envVarApiKey} or ${this.envVarSearchEngineId}
- Missing data in response from the STT API
- Failed to fetch URL: ${response.status} ${response.statusTex
AI-assisted analysis of danny-avila/LibreChat@5ff282f900 (2026-08-12).
Data as JSON: /api/errors/4a4c600a0027e852.
Report an issue: GitHub.