{"record":{"id":"7d7afd6f3b0fca7e","repo":"jackwener/OpenCLI","slug":"guazi-contexthint-network-error-err-message","errorCode":null,"errorMessage":"guazi ${contextHint} network error: ${err?.message || err}","messagePattern":"guazi (.+?) network error: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/guazi/utils.js","lineNumber":117,"sourceCode":"export function requireStableId(value, label) {\n    const id = String(value ?? '').trim();\n    if (!/^\\d+$/.test(id)) throw new CommandExecutionError(`${label} did not include a stable numeric id.`);\n    return id;\n}\n\n/** Fetch a Guazi mobile page as HTML text, throwing typed errors. */\nexport async function guaziFetch(path, contextHint) {\n    let resp;\n    try {\n        resp = await fetch(`${GUAZI_M_BASE}${path}`, {\n            headers: {\n                'User-Agent': UA,\n                Referer: `${GUAZI_M_BASE}/`,\n                'Accept-Language': 'zh-CN,zh;q=0.9',\n            },\n        });\n    } catch (err) {\n        throw new CommandExecutionError(`guazi ${contextHint} network error: ${err?.message || err}`);\n    }\n    if (!resp.ok) {\n        throw new CommandExecutionError(`guazi ${contextHint} HTTP ${resp.status}`);\n    }\n    const html = await resp.text();\n    // Guazi may eventually push the mobile pages behind their JS challenge.\n    if (/瑞数|reese84|captcha|滑动验证|verify\\.guazi|安全验证/i.test(html) && !/car-detail\\/c\\d+/.test(html)) {\n        throw new AuthRequiredError(\n            'guazi.com',\n            `guazi ${contextHint} hit an anti-bot challenge — Guazi may have started gating the mobile site.`,\n        );\n    }\n    return html;\n}\n\nexport { ArgumentError, CommandExecutionError, EmptyResultError };\n","sourceCodeStart":99,"sourceCodeEnd":134,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/guazi/utils.js#L99-L134","documentation":"guaziFetch wraps its fetch of a Guazi mobile page in try/catch and rethrows any network-level failure (DNS, TLS, timeout, connection refused, abort) as a CommandExecutionError with the contextHint and underlying message. It exists so scraping commands fail with a typed, descriptive error instead of an opaque fetch exception.","triggerScenarios":"Calling guaziFetch(path, contextHint) when the network request to GUAZI_M_BASE throws: no internet, DNS resolution failure for guazi.com, TLS errors, request timeouts/aborts, or proxy failures. Non-2xx responses do NOT hit this path (see HTTP error).","commonSituations":"Running the CLI offline or behind a restrictive corporate proxy; DNS/ad-blocker blocking guazi.com; Node fetch TLS certificate issues; transient connection resets from the Guazi mobile site.","solutions":["Check basic connectivity: curl -I https://www.guazi.com/ (or the underlying err.message for the exact cause)","Configure HTTPS_PROXY/HTTP_PROXY env vars if a proxy is required","Retry the command — transient connection resets are common with scraped sites","Inspect err?.message embedded in the error text to identify DNS vs TLS vs timeout"],"exampleFix":"// before\nawait guaziFetch('/car/123', 'car page'); // offline\n// CommandExecutionError: guazi car page network error: fetch failed\n\n// after\nif (!navigator.onLine) throw new Error('go online first');\nawait guaziFetch('/car/123', 'car page');","handlingStrategy":"retry","validationCode":"// check connectivity before calling\nconst ok = await fetch('https://guazi.com/', { method: 'HEAD' }).then(() => true).catch(() => false);\nif (!ok) throw new Error('no network access to guazi.com');","typeGuard":"const isNetworkError = (e) => e instanceof CommandExecutionError && /network error/.test(e.message);","tryCatchPattern":"try {\n  const html = await guaziFetch(path, hint);\n} catch (e) {\n  if (isNetworkError(e) && isRetryable(e)) return retryWithBackoff(() => guaziFetch(path, hint), 3);\n  throw e;\n}","preventionTips":["Configure proxy env vars (HTTPS_PROXY) when behind a corporate network","Implement exponential backoff retries around guaziFetch","Fail fast with a connectivity check before long scrape runs","Log the embedded cause (err?.message) for diagnosis"],"tags":["network","fetch","scraping"],"backgroundTag":"connection-refused","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}