{"record":{"id":"e1d8d02fc9223d83","repo":"jackwener/OpenCLI","slug":"label-request-failed-err-message-e1d8d0","errorCode":null,"errorMessage":"${label} request failed: ${err.message}","messagePattern":"(.+?) request failed: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"critical","filePath":"clis/wttr/utils.js","lineNumber":25,"sourceCode":"\nexport const WTTR_BASE = 'https://wttr.in';\nconst UA = 'opencli-wttr/1.0';\n\nexport function requireString(value, name) {\n    if (typeof value !== 'string' || !value.trim()) {\n        throw new ArgumentError(`--${name} is required`);\n    }\n    return value.trim();\n}\n\nexport async function wttrFetch(location, label) {\n    // wttr.in path-encodes the location. Spaces → %20 is fine; commas survive.\n    const url = `${WTTR_BASE}/${encodeURIComponent(location)}?format=j1`;\n    let resp;\n    try {\n        resp = await fetch(url, { headers: { 'User-Agent': UA, accept: 'application/json' } });\n    } catch (err) {\n        throw new CommandExecutionError(`${label} request failed: ${err.message}`);\n    }\n    if (resp.status === 404) {\n        throw new EmptyResultError(label, `${label} could not find location \"${location}\".`);\n    }\n    if (!resp.ok) {\n        throw new CommandExecutionError(`${label} returned HTTP ${resp.status}.`);\n    }\n    let body;\n    try {\n        body = await resp.json();\n    } catch (err) {\n        // wttr.in falls back to plain-text \"Unknown location\" for some bad inputs;\n        // promote that to EmptyResult instead of pretending we got JSON.\n        throw new EmptyResultError(label, `${label} returned non-JSON body (likely unknown location).`);\n    }\n    return body;\n}\n","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/wttr/utils.js#L7-L43","documentation":"This CommandExecutionError wraps a low-level fetch failure when the HTTP request to wttr.in never completes — the fetch call itself rejected (DNS failure, connection refused/reset, timeout, TLS error). The label ('wttr forecast', etc.) is prefixed and the underlying err.message is appended for diagnosis.","triggerScenarios":"wttrFetch calls fetch(`https://wttr.in/${encodeURIComponent(location)}?format=j1`) and the promise rejects before a response object exists.","commonSituations":"Being offline or behind a blocking corporate proxy; DNS resolution failure; firewall blocking wttr.in; Node without network access in CI; TLS interception.","solutions":["Verify network connectivity and DNS for wttr.in (curl -v 'https://wttr.in/Paris?format=j1')","Configure proxy environment variables (HTTPS_PROXY) if behind a proxy","Retry with backoff for transient connection issues","Set up a fallback weather source (e.g. NWS for US locations)"],"exampleFix":"// before\nconst body = await wttrFetch(location, 'wttr forecast'); // throws offline\n// after\ntry {\n  const body = await wttrFetch(location, 'wttr forecast');\n} catch (err) {\n  if (err instanceof CommandExecutionError) body = await fallbackFetch(location);\n  else throw err;\n}","handlingStrategy":"retry","validationCode":"// Pre-flight connectivity check\ntry {\n  await fetch('https://wttr.in/?format=j1', { method: 'HEAD' });\n} catch {\n  throw new Error('wttr.in is unreachable; check network/proxy');\n}","typeGuard":null,"tryCatchPattern":"try {\n  result = await forecast({ location });\n} catch (err) {\n  if (err instanceof CommandExecutionError && err.message.includes('request failed')) {\n    // transient network issue: retry with backoff\n    result = await withRetry(() => forecast({ location }), 3);\n  } else throw err;\n}","preventionTips":["Set HTTPS_PROXY/HTTP_PROXY when behind corporate proxies","Implement retry with exponential backoff for transient failures","Monitor wttr.in uptime and cache last successful responses as fallback"],"tags":["network","fetch","request-failed"],"backgroundTag":"request-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}