{"record":{"id":"a93b8e2bd8a1ee98","repo":"jackwener/OpenCLI","slug":"fetch-error-a93b8e","errorCode":"FETCH_ERROR","errorMessage":"HTTP ${resp.status}","messagePattern":"HTTP \\$\\{resp\\.status\\}","errorType":"error_code","errorClass":"CliError","httpStatus":null,"severity":"error","filePath":"clis/google/suggest.js","lineNumber":25,"sourceCode":"cli({\n    site: 'google',\n    name: 'suggest',\n    access: 'read',\n    description: 'Get Google search suggestions',\n    strategy: Strategy.PUBLIC,\n    browser: false,\n    args: [\n        { name: 'keyword', positional: true, required: true, help: 'Search query' },\n        { name: 'lang', default: 'zh-CN', help: 'Language code' },\n    ],\n    columns: ['suggestion'],\n    func: async (args) => {\n        const keyword = encodeURIComponent(args.keyword);\n        const lang = encodeURIComponent(args.lang);\n        const url = `https://suggestqueries.google.com/complete/search?client=firefox&q=${keyword}&hl=${lang}`;\n        const resp = await fetch(url);\n        if (!resp.ok) {\n            throw new CliError('FETCH_ERROR', `HTTP ${resp.status}`, 'Check your network connection');\n        }\n        const data = await resp.json();\n        // Response format: [\"query\", [\"suggestion1\", \"suggestion2\", ...]]\n        const suggestions = Array.isArray(data) && Array.isArray(data[1]) ? data[1] : [];\n        if (!suggestions.length) {\n            throw new CliError('NOT_FOUND', 'No suggestions found', 'Try a different keyword');\n        }\n        return suggestions.map(s => ({ suggestion: s }));\n    },\n});\n","sourceCodeStart":7,"sourceCodeEnd":36,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/google/suggest.js#L7-L36","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nconst resp = await fetch(url);\nif (!resp.ok) throw new CliError('FETCH_ERROR', `HTTP ${resp.status}`, 'Check your network connection');\n// after\nconst resp = await fetch(url, {headers: {'User-Agent': 'Mozilla/5.0'}});\nif (resp.status === 429) await backoff();\nif (!resp.ok) throw new CliError('FETCH_ERROR', `HTTP ${resp.status}`, 'Check your network connection');","handlingStrategy":"retry","validationCode":"// validate keyword before calling\nif (!keyword || !keyword.trim()) throw new Error('keyword required');","typeGuard":"function isSuggestPayload(data) {\n  return Array.isArray(data) && Array.isArray(data[1]);\n}","tryCatchPattern":"try {\n  return await suggestCommand.func(args);\n} catch (e) {\n  if (e.code === 'FETCH_ERROR' && e.message.includes('429')) {\n    await sleep(10000);\n    return suggestCommand.func(args);\n  }\n  throw e;\n}","preventionTips":["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"],"tags":["network","http","google","autocomplete"],"backgroundTag":"http-request-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}