jackwener/OpenCLI · error · CommandExecutionError
guazi browse ${code}
Error message
guazi browse ${code} What it means
The 'guazi browse' command fetched the Guazi mobile SSR listing page successfully but parseListings found zero listing anchor elements. The CLI deliberately throws CommandExecutionError instead of returning an empty result, because an empty page usually means the site's HTML layout changed (or the city page has no cars), not that there is genuinely nothing to show.
Source
Thrown at clis/guazi/browse.js:88
site: 'guazi',
name: 'browse',
access: 'read',
aliases: ['list'],
description: '瓜子二手车在售车源列表(按城市,含售价/首付/里程/年份)',
strategy: Strategy.PUBLIC,
browser: false,
args: [
{ name: 'city', positional: true, help: '城市名(北京/上海/...)或瓜子城市码(bj/sh/...)。默认 bj 北京' },
{ name: 'limit', type: 'int', default: 20, help: '返回的车源数量(最多 40,单页 SSR 上限)' },
],
columns: BROWSE_COLUMNS,
func: async (args) => {
const code = resolveCityCode(args.city);
const limit = requireLimit(args.limit, 20, 40);
const html = await guaziFetch(`/${code}/buy/`, `browse ${code}`);
const rows = parseListings(html, limit);
if (rows.length === 0) {
throw new CommandExecutionError(
`guazi browse ${code}`,
'No SSR listing anchors found on a successful Guazi mobile page; the mobile layout may have changed.',
);
}
return rows;
},
});
View on GitHub (pinned to 49907e53dc)
Solutions
- Re-run with a different city (e.g. bj) to see if it is city-specific or site-wide.
- Fetch https://m.guazi.com/<code>/buy/ in a browser and confirm whether listing anchors still appear in the server-rendered HTML.
- Update the parseListings selectors in clis/guazi to match the new markup.
- If the site is now client-rendered, switch to a headless browser or the underlying data API.
Example fix
// before (assuming old selector)
const anchors = doc.querySelectorAll('a[href*="/car"]');
// after (match the new markup discovered by inspecting the page)
const anchors = doc.querySelectorAll('a.carlist-item, a[href*="/buy/detail"]'); Defensive patterns
Strategy: fallback
Validate before calling
const html = await fetch(`https://m.guazi.com/${code}/buy/`).then(r => r.text());
if (!/<a[^>]+href=["']?[^"']*car/i.test(html)) {
console.warn('No SSR anchors present — layout may have changed');
} Type guard
function hasListings(html) {
return typeof html === 'string' && /<a\s[^>]*href="[^"]*\/(buy\/)?detail/i.test(html);
} Try / catch
try {
const rows = await guaziBrowse({ city });
} catch (e) {
if (/No SSR listing anchors/.test(e.message)) {
console.warn('Guazi layout may have changed; check m.guazi.com in a browser');
return [];
}
throw e;
} Prevention
- Pin/monitor the HTML structure of the listing page with a periodic smoke test
- Handle empty results gracefully instead of crashing pipelines
- Try a second city to distinguish layout change from empty inventory
- Keep selectors broad and add fallback selectors
When it happens
Trigger: Running 'guazi browse --city <code>' when Guazi's mobile page (/<code>/buy/) renders no <a> listing anchors — e.g. the site switched to client-side rendering, changed anchor markup/classes, or the city code resolves to a page with no inventory and an unexpectedly empty SSR body.
Common situations: Guazi front-end redesign or A/B test removing server-rendered anchors; scraping from a region where the mobile layout differs; city code pointing to a city with no used-car listings; bot-detection serving a JS-only shell page.
Related errors
- ${label} did not include a stable text value.
- autohome brand catalog returned an unexpected HTML shape; ex
- No series found for '${brand}'. Check the brand name spellin
- No koubei data found — the series id may be wrong, or Autoho
- This series has no koubei rating yet.
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/3e77530b6de6ce57.
Report an issue: GitHub.