jackwener/OpenCLI · error · CommandExecutionError
Ctrip cruise cards rendered but parser did not find required
Error message
Ctrip cruise cards rendered but parser did not find required itinerary anchors
What it means
CommandExecutionError thrown when the extraction script returns a well-formed but EMPTY array even though the page rendered (wait state was 'content'). The CLI distinguishes this from EmptyResultError: cards are visibly on the page, but buildCruiseExtractJs could not find the required itinerary anchors (e.g. links/fields inside .route_info cards it needs to build rows). This almost always means Ctrip changed its card markup so the parser's selectors no longer match.
Source
Thrown at clis/ctrip/cruise.js:83
await page.goto(searchUrl);
const portWait = await page.evaluate(WAIT_FOR_CRUISE_JS);
if (portWait === 'captcha') {
throw new AuthRequiredError('cruise.ctrip.com', 'Ctrip is asking for a captcha; complete it in your browser session and retry');
}
if (portWait === 'empty') {
throw new EmptyResultError('ctrip cruise', `No cruises currently departing "${port}"`);
}
if (portWait !== 'content') {
throw new CommandExecutionError(`Ctrip cruise port page did not render (state=${String(portWait)})`);
}
}
const raw = await page.evaluate(buildCruiseExtractJs());
if (!Array.isArray(raw)) {
throw new CommandExecutionError('Ctrip cruise DOM extraction returned malformed rows');
}
if (raw.length === 0) {
throw new CommandExecutionError('Ctrip cruise cards rendered but parser did not find required itinerary anchors');
}
return raw.slice(0, limit).map((r, i) => ({
rank: i + 1,
title: r.title,
star: r.star,
boarding: r.boarding,
sailingDate: r.sailingDate,
tags: r.tags,
price: r.price,
url: searchUrl,
}));
},
});
View on GitHub (pinned to 49907e53dc)
Solutions
- Open the port results page in a browser DevTools and diff the actual card markup against the selectors in buildCruiseExtractJs (clis/ctrip/utils.js)
- Update/fix the extraction selectors in clis/ctrip/utils.js to match the current .route_info structure
- Upgrade the opencli package in case a newer version already tracks the new Ctrip markup
- Add a short settle delay/scroll before extraction if anchors attach late during lazy hydration
Example fix
// before (utils.js): anchor selector outdated
const link = card.querySelector('a.itinerary-link');
if (!link) return null;
// after: match new markup (verify in DevTools)
const link = card.querySelector('a[href*="/cruise/"], .route_title a');
if (!link) return null; Defensive patterns
Strategy: validation
Validate before calling
// Validate the required anchors still exist in the live DOM before full extraction
const anchorsOk = await page.evaluate(() =>
document.querySelectorAll('.route_info a').length > 0
);
if (!anchorsOk) console.error('Ctrip card markup changed; update buildCruiseExtractJs selectors'); Type guard
function isParserMissError(e) {
return e instanceof Error && e.name === 'CommandExecutionError' && /itinerary anchors/.test(e.message);
} Try / catch
try {
return await run(['ctrip', 'cruise', port]);
} catch (e) {
if (isParserMissError(e)) {
console.error('Ctrip markup likely changed — inspect .route_info in DevTools and update selectors');
throw e;
}
throw e;
} Prevention
- Add a smoke test that runs the cruise command weekly to detect selector drift early
- Diff .route_info card markup against extractor selectors after any Ctrip UI change notice
- Keep opencli updated — fixes for markup changes land there first
- Add a settle delay before extraction if anchors attach during late hydration
When it happens
Trigger: Calling `ctrip cruise <port>` where the page passed the content probe but the extraction script's required itinerary anchor selectors (inside .route_info cards) matched zero elements — markup redesign, renamed classes, or content moved behind lazy-loaded subcomponents after the probe ran.
Common situations: Ctrip front-end redeploy changing .route_info internals (A/B tests, redesigns); CLI version older than a recent site markup change; region-specific page variants (overseas ports) rendered with slightly different DOM; partial lazy-load so cards exist but their anchors haven't attached yet.
Related errors
- Ctrip ferry rows rendered but parser did not find required s
- Ctrip round-trip flight cards rendered but parser did not fi
- Ctrip cruise DOM extraction returned malformed rows
- Ctrip ferry DOM extraction returned malformed rows
- Ctrip round-trip flight DOM extraction returned malformed ro
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/ef5db60cb678876b.
Report an issue: GitHub.