jackwener/OpenCLI · error · CliError
FETCH_ERROR
FETCH_ERROR
Error message
HTTP ${resp.status} What it means
The google suggest command calls Google's completion endpoint (suggestqueries.google.com/complete/search?client=firefox) and throws this CliError with code FETCH_ERROR when the HTTP response is not ok. It converts any non-2xx status into a single FETCH_ERROR with a network-connection hint.
Source
Thrown at clis/google/suggest.js:25
cli({
site: 'google',
name: 'suggest',
access: 'read',
description: 'Get Google search suggestions',
strategy: Strategy.PUBLIC,
browser: false,
args: [
{ name: 'keyword', positional: true, required: true, help: 'Search query' },
{ name: 'lang', default: 'zh-CN', help: 'Language code' },
],
columns: ['suggestion'],
func: async (args) => {
const keyword = encodeURIComponent(args.keyword);
const lang = encodeURIComponent(args.lang);
const url = `https://suggestqueries.google.com/complete/search?client=firefox&q=${keyword}&hl=${lang}`;
const resp = await fetch(url);
if (!resp.ok) {
throw new CliError('FETCH_ERROR', `HTTP ${resp.status}`, 'Check your network connection');
}
const data = await resp.json();
// Response format: ["query", ["suggestion1", "suggestion2", ...]]
const suggestions = Array.isArray(data) && Array.isArray(data[1]) ? data[1] : [];
if (!suggestions.length) {
throw new CliError('NOT_FOUND', 'No suggestions found', 'Try a different keyword');
}
return suggestions.map(s => ({ suggestion: s }));
},
});
View on GitHub (pinned to 49907e53dc)
Solutions
- If 429, throttle request rate and add exponential backoff between suggest calls
- Send a browser-like User-Agent header if the endpoint returns 403
- Retry after a delay for 5xx statuses, which are usually transient
- Verify network/proxy connectivity if all requests fail
- Log resp.status so the actual cause (rate-limit vs server error) is visible
Example fix
// before
const resp = await fetch(url);
if (!resp.ok) throw new CliError('FETCH_ERROR', `HTTP ${resp.status}`, 'Check your network connection');
// after
const resp = await fetch(url, {headers: {'User-Agent': 'Mozilla/5.0'}});
if (resp.status === 429) await backoff();
if (!resp.ok) throw new CliError('FETCH_ERROR', `HTTP ${resp.status}`, 'Check your network connection'); Defensive patterns
Strategy: retry
Validate before calling
// validate keyword before calling
if (!keyword || !keyword.trim()) throw new Error('keyword required'); Type guard
function isSuggestPayload(data) {
return Array.isArray(data) && Array.isArray(data[1]);
} Try / catch
try {
return await suggestCommand.func(args);
} catch (e) {
if (e.code === 'FETCH_ERROR' && e.message.includes('429')) {
await sleep(10000);
return suggestCommand.func(args);
}
throw e;
} Prevention
- Throttle autocomplete requests; suggest endpoints rate-limit aggressively
- Send a browser-like User-Agent to avoid 403s
- Use exponential backoff on FETCH_ERROR
- Confirm network/proxy allows suggestqueries.google.com
When it happens
Trigger: fetch() to the suggest endpoint returns resp.ok === false — typically HTTP 429 after too many autocomplete requests, 403 bot rejection, or a proxy/network layer returning an error status.
Common situations: Bulk keyword-research loops hammering the suggest endpoint from one IP; missing or blocked User-Agent causing 403; corporate proxy intercepting the request; transient Google-side 5xx.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- FETCH_ERROR
- FETCH_ERROR
- 12306 queryByTrainNo returned HTTP ${resp.status}
- 12306 queryByTrainNo returned non-JSON body
- 12306 ${endpoint} returned non-JSON body
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/a93b8e2bd8a1ee98.
Report an issue: GitHub.