jackwener/OpenCLI · error · CommandExecutionError
${label} did not include a stable text value.
Error message
${label} did not include a stable text value. What it means
requireText cleans whitespace from an extracted value and throws CommandExecutionError when the result is empty, using the caller's label (e.g. 'guazi car 100200300 title'). It guards against HTML pages that return 200 but fail to contain the expected field, which would otherwise silently produce blank data.
Source
Thrown at clis/guazi/utils.js:95
return m[1];
}
export function requireLimit(value, def, max) {
const raw = value == null || value === '' ? def : value;
const n = typeof raw === 'number' ? raw : Number(String(raw).trim());
if (!Number.isInteger(n) || n < 1 || n > max) {
throw new ArgumentError(`limit must be an integer between 1 and ${max}`);
}
return n;
}
export function clean(s) {
return String(s == null ? '' : s).replace(/\s+/g, ' ').trim();
}
export function requireText(value, label) {
const text = clean(value);
if (!text) throw new CommandExecutionError(`${label} did not include a stable text value.`);
return text;
}
export function requireStableId(value, label) {
const id = String(value ?? '').trim();
if (!/^\d+$/.test(id)) throw new CommandExecutionError(`${label} did not include a stable numeric id.`);
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',View on GitHub (pinned to 49907e53dc)
Solutions
- Open the detail page in a browser and confirm the title renders in server HTML; if not, the layout/rendering changed.
- Update the parser in clis/guazi/car.js to select the new title element so requireText receives a value.
- Re-run with a different car id to determine whether it is page-specific or template-wide.
- If pages are bot-degraded, add proper headers/cookies or slow request rate before retrying.
Example fix
// before
const title = doc.querySelector('.car-name')?.textContent;
// after (selector updated to current markup)
const title = doc.querySelector('h1.car-title, .detail-title')?.textContent; Defensive patterns
Strategy: try-catch
Validate before calling
const text = (value ?? '').replace(/\s+/g, ' ').trim();
if (!text) console.warn(`No text extracted for ${label} — check page markup`); Type guard
function hasText(v): v is string {
return typeof v === 'string' && v.replace(/\s+/g, ' ').trim().length > 0;
} Try / catch
try {
const car = await guaziCar({ clue_id: id });
} catch (e) {
if (/did not include a stable text value/.test(e.message)) {
console.warn(`Field missing for car ${id}; page template may have changed`);
return null;
}
throw e;
} Prevention
- Add broad/fallback CSS selectors for key fields
- Spot-check rendered HTML when parsing silently degrades
- Treat missing-field errors as layout-change signals, not data noise
- Keep a fixture HTML test that asserts title extraction still works
When it happens
Trigger: 'guazi car <clueId>' found rows but the title field parsed to null/empty/whitespace — e.g. the detail template renamed the title element, the field moved behind JS rendering, or anti-bot returned a degraded page shell.
Common situations: Guazi redesign moving the <h1>/title node; scraping a page where the listing exists but title loads client-side; empty string in a scraped <td> due to a layout variant; partial page served to suspected bots.
Related errors
- guazi browse ${code}
- 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/722ca2762db95c0d.
Report an issue: GitHub.