{"record":{"id":"252f2b1ddc6e2935","repo":"jackwener/OpenCLI","slug":"request-failed","errorCode":"REQUEST_FAILED","errorMessage":"Failed to request Gitee search API: ${response.status}","messagePattern":"Failed to request Gitee search API: (.+?)","errorType":"error_code","errorClass":"CliError","httpStatus":null,"severity":"error","filePath":"clis/gitee/search.js","lineNumber":100,"sourceCode":"        const limit = clampLimit(args.limit);\n        const encodedKeyword = encodeURIComponent(keyword);\n        const searchUrl = `${GITEE_SEARCH_URL}?q=${encodedKeyword}&type=repository`;\n        const fetchSize = Math.max(10, limit);\n        const apiUrl = new URL(GITEE_SEARCH_API);\n        apiUrl.searchParams.set('q', keyword);\n        apiUrl.searchParams.set('from', '0');\n        apiUrl.searchParams.set('size', String(fetchSize));\n        await page.goto(searchUrl);\n        await page.wait(2);\n        const response = await fetch(apiUrl.toString(), {\n            headers: {\n                Accept: 'application/json',\n                'User-Agent': 'Mozilla/5.0',\n                Referer: searchUrl,\n            },\n        });\n        if (!response.ok) {\n            throw new CliError('REQUEST_FAILED', `Failed to request Gitee search API: ${response.status}`, 'Try again later or verify network access to so.gitee.com');\n        }\n        const payload = await response.json();\n        const payloadRecord = asRecord(payload);\n        const hitsRecord = asRecord(payloadRecord?.hits);\n        const rawRows = Array.isArray(hitsRecord?.hits) ? hitsRecord.hits : [];\n        if (rawRows.length === 0) {\n            throw new CliError('NOT_FOUND', 'No Gitee repository search results found', 'Try a different keyword or check whether Gitee search API changed');\n        }\n        const seen = new Set();\n        const rows = [];\n        for (let i = 0; i < rawRows.length && rows.length < limit; i++) {\n            const row = asRecord(rawRows[i]);\n            const fields = asRecord(row?.fields);\n            if (!fields)\n                continue;\n            const name = normalizeText(getFirstText(fields.title));\n            const repoUrl = normalizeUrl(getFirstText(fields.url));\n            if (!name || !repoUrl)","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/gitee/search.js#L82-L118","documentation":"CliError with code REQUEST_FAILED thrown when the HTTP response from the Gitee search API (so.gitee.com) has a non-ok status. The library surfaces the status code and advises retrying later or verifying network access to so.gitee.com. It indicates the upstream request failed before any result parsing.","triggerScenarios":"fetch(GITEE_SEARCH_API) returns response.ok === false — e.g. HTTP 403/429 (rate limit / bot detection), 5xx server errors, or a proxy error while requesting the search endpoint with the browser-context headers (Accept json, Mozilla UA, Referer: searchUrl).","commonSituations":"Gitee rate-limiting or WAF blocking automated requests; so.gitee.com temporarily down or returning 5xx; corporate proxy/firewall blocking so.gitee.com; stale session cookies triggering 403; API endpoint changed and now rejects the request.","solutions":["Retry after a delay; the hint suggests 'Try again later' for transient 5xx/429","Check network access to so.gitee.com (curl -I https://so.gitee.com) and proxy/VPN settings","Reduce request frequency to avoid Gitee rate limiting/bot detection","Log response.status and inspect the body to see if Gitee changed or blocked the API","Fall back to scraping the search HTML page or use Gitee's official REST API with a token"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Pre-flight connectivity check\nconst res = await fetch('https://so.gitee.com', { method: 'HEAD' }).catch(() => null);\nif (!res) { console.error('so.gitee.com unreachable — check network/proxy'); process.exit(1); }","typeGuard":"function isRequestFailed(e) {\n  return e instanceof Error && e.code === 'REQUEST_FAILED';\n}","tryCatchPattern":"try {\n  rows = await giteeSearch(keyword);\n} catch (e) {\n  if (e.code === 'REQUEST_FAILED') {\n    // exponential backoff retry for transient 429/5xx\n    await sleep(2000);\n    rows = await giteeSearch(keyword);\n  } else throw e;\n}","preventionTips":["Add exponential backoff with jitter on 429/5xx responses","Throttle request rate to stay under Gitee rate limits","Keep browser-context headers (UA, Referer) intact when calling the endpoint","Monitor so.gitee.com availability and alert on sustained failures"],"tags":["network","http","gitee","rate-limit"],"backgroundTag":"http-request-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}