jackwener/OpenCLI · error · CommandExecutionError
guazi ${contextHint} HTTP ${resp.status}
Error message
guazi ${contextHint} HTTP ${resp.status} What it means
guaziFetch checks resp.ok after the request succeeds at the transport level and throws CommandExecutionError for any non-OK HTTP status (404, 403, 500, rate-limit 429, etc.), embedding the status code and contextHint. This distinguishes server-side rejections from network failures.
Source
Thrown at clis/guazi/utils.js:120
return id;
}
/** Fetch a Guazi mobile page as HTML text, throwing typed errors. */
export async function guaziFetch(path, contextHint) {
let resp;
try {
resp = await fetch(`${GUAZI_M_BASE}${path}`, {
headers: {
'User-Agent': UA,
Referer: `${GUAZI_M_BASE}/`,
'Accept-Language': 'zh-CN,zh;q=0.9',
},
});
} catch (err) {
throw new CommandExecutionError(`guazi ${contextHint} network error: ${err?.message || err}`);
}
if (!resp.ok) {
throw new CommandExecutionError(`guazi ${contextHint} HTTP ${resp.status}`);
}
const html = await resp.text();
// Guazi may eventually push the mobile pages behind their JS challenge.
if (/瑞数|reese84|captcha|滑动验证|verify\.guazi|安全验证/i.test(html) && !/car-detail\/c\d+/.test(html)) {
throw new AuthRequiredError(
'guazi.com',
`guazi ${contextHint} hit an anti-bot challenge — Guazi may have started gating the mobile site.`,
);
}
return html;
}
export { ArgumentError, CommandExecutionError, EmptyResultError };
View on GitHub (pinned to 49907e53dc)
Solutions
- Log resp.status from the error message and check it: 404 means bad id/path, 403/429 means blocked
- Add delays/backoff between requests to avoid rate-limiting
- Verify the car id or path is correct by opening it in a browser
- Rotate IP/proxy if consistently 403/429
Example fix
// before
await guaziFetch('/car/99999999999', 'car page'); // 404
// guazi car page HTTP 404
// after
const listing = await findLiveCarId(query); // resolve a valid id first
await guaziFetch(`/car/${listing.id}`, 'car page'); Defensive patterns
Strategy: retry
Validate before calling
// verify the target page exists before scraping
const HEAD = await fetch(`${GUAZI_M_BASE}${path}`, { method: 'HEAD' });
if (HEAD.status === 404) throw new Error('listing not found'); Type guard
const isHttpError = (e) => e instanceof CommandExecutionError && /HTTP \d+/.test(e.message);
Try / catch
try {
const html = await guaziFetch(path, hint);
} catch (e) {
const m = e.message.match(/HTTP (\d+)/);
if (m && ['429','500','502','503'].includes(m[1])) return retryWithBackoff(() => guaziFetch(path, hint), 3);
throw e;
} Prevention
- Throttle requests with delays to avoid 403/429 rate limits
- Treat 404 as a permanent failure — do not retry
- Rotate proxies/IPs if you see repeated 403s
- Monitor Guazi status; 5xx bursts usually indicate server-side incidents
When it happens
Trigger: guaziFetch(path, contextHint) receiving a response with resp.ok === false: a deleted/invalid car listing (404), IP rate-limiting or WAF block (403/429), or Guazi server errors (5xx).
Common situations: Scraping a car id that no longer exists; hitting Guazi too frequently from one IP and getting rate-limited; the mobile endpoint path changed in a site redesign.
Related errors
- 1point3acres request failed: HTTP ${res.status} ${res.status
- Barchart greeks request failed: HTTP ${data.status}${data.st
- github-trending request failed: HTTP ${resp.status}
- hf datasets failed: HTTP ${resp.status}
- HTTP ${code}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/53fb985042718562.
Report an issue: GitHub.