{"record":{"id":"4209da44e4201620","repo":"jackwener/OpenCLI","slug":"stack-exchange-request-failed-error-message","errorCode":null,"errorMessage":"stack exchange request failed: ${error?.message || error}","messagePattern":"stack exchange request failed: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"critical","filePath":"clis/stackoverflow/utils.js","lineNumber":60,"sourceCode":"    if (searchParams) {\n        for (const [k, v] of Object.entries(searchParams)) {\n            if (v == null || v === '') continue;\n            url.searchParams.set(k, String(v));\n        }\n    }\n    if (!url.searchParams.has('site')) url.searchParams.set('site', SE_SITE);\n\n    let resp;\n    try {\n        resp = await fetch(url, {\n            headers: {\n                'Accept': 'application/json',\n                'Accept-Encoding': 'gzip',\n                'User-Agent': UA,\n            },\n        });\n    } catch (error) {\n        throw new CommandExecutionError(`stack exchange request failed: ${error?.message || error}`);\n    }\n    if (resp.status === 429) {\n        throw new CommandExecutionError('stack exchange returned HTTP 429 (rate limited)', 'Wait a few seconds and retry, or lower --limit.');\n    }\n    if (!resp.ok) {\n        let body = '';\n        try { body = (await resp.json())?.error_message || ''; } catch { /* ignore */ }\n        throw new CommandExecutionError(`stack exchange HTTP ${resp.status}: ${body || resp.statusText}`);\n    }\n    let data;\n    try {\n        data = await resp.json();\n    } catch (error) {\n        throw new CommandExecutionError(`stack exchange returned malformed JSON: ${error?.message || error}`);\n    }\n    if (data?.error_id) {\n        throw new CommandExecutionError(\n            `stack exchange API error: ${data.error_message || data.error_name}`,","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/stackoverflow/utils.js#L42-L78","documentation":"CommandExecutionError thrown by seFetch when the underlying fetch() call itself rejects — the request never got an HTTP response. The original error message is wrapped as `stack exchange request failed: <cause>` so DNS failures, TLS errors, connection resets, and timeouts all surface under this single prefix.","triggerScenarios":"No network/DNS failure resolving api.stackexchange.com; TLS/proxy interception (corporate MITM); IPv6 issues; Node runtime without global fetch (Node < 18); firewall blocking outbound 443.","commonSituations":"Working offline or on flaky Wi-Fi; corporate proxy requiring custom CA certs; DNS blocked by VPN; CI runners without egress to api.stackexchange.com.","solutions":["Check connectivity: `curl -sI https://api.stackexchange.com/2.3/info?site=stackoverflow`.","Fix DNS/VPN/proxy issues; if behind a MITM proxy, configure NODE_EXTRA_CA_CERTS or HTTPS_PROXY correctly.","Ensure Node >= 18 so global fetch exists.","Retry with backoff on transient network errors before giving up."],"exampleFix":"// before\nconst data = await seFetch(path);\n// after\nlet data;\nfor (let i = 0; i < 3; i++) {\n  try { data = await seFetch(path); break; }\n  catch (e) {\n    if (!String(e.message).startsWith('stack exchange request failed') || i === 2) throw e;\n    await new Promise(r => setTimeout(r, 1000 * 2 ** i));\n  }\n}","handlingStrategy":"retry","validationCode":"if (typeof fetch !== 'function') throw new Error('global fetch unavailable; requires Node >= 18');\n// optional preflight:\nawait fetch('https://api.stackexchange.com/2.3/info?site=stackoverflow', { method: 'HEAD' });","typeGuard":null,"tryCatchPattern":"async function fetchWithRetry(path, attempts = 3) {\n  for (let i = 0; ; i++) {\n    try {\n      return await seFetch(path);\n    } catch (e) {\n      const transient = String(e.message).startsWith('stack exchange request failed');\n      if (!transient || i >= attempts - 1) throw e;\n      await new Promise(r => setTimeout(r, 1000 * 2 ** i));\n    }\n  }\n}","preventionTips":["Verify egress to api.stackexchange.com:443 from the environment (curl/DNS check) before running batch jobs.","Run Node >= 18 so global fetch is available.","Configure HTTPS_PROXY/NODE_EXTRA_CA_CERTS when behind a corporate proxy.","Use exponential backoff with a retry budget for network-layer failures."],"tags":["network","fetch-failed","dns","stack-exchange-api"],"backgroundTag":"fetch-request-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}