jackwener/OpenCLI · error · CommandExecutionError
Ctrip round-trip flight DOM extraction returned malformed ro
Error message
Ctrip round-trip flight DOM extraction returned malformed rows
What it means
A CommandExecutionError thrown when the in-page extraction script returns a non-array value, meaning the DOM extraction phase itself failed structurally rather than finding zero flights. This is treated as a scraper/contract violation (malformed rows), distinct from an empty but valid result (EmptyResultError).
Source
Thrown at clis/ctrip/flight-round.js:92
throw new ArgumentError(`--return (${ret}) must be on or after --depart (${depart})`);
}
const limit = parseListLimit(kwargs.limit);
const searchUrl =
`https://flights.ctrip.com/online/list/round-${fromCode.toLowerCase()}-${toCode.toLowerCase()}` +
`?depdate=${depart}_${ret}&cabin=Y_S_C_F&adult=1&child=0&infant=0`;
await page.goto(searchUrl);
const waitResult = await page.evaluate(WAIT_FOR_FLIGHTS_ROUND_JS);
if (waitResult === 'captcha') {
throw new AuthRequiredError('flights.ctrip.com', 'Ctrip is asking for a captcha; complete it in your browser session and retry');
}
if (waitResult !== 'content') {
throw new CommandExecutionError(`Ctrip round-trip flight page did not render flight cards (state=${String(waitResult)})`);
}
const renderedCardCount = await page.evaluate(buildScrollUntilJs(ROUND_CARD_SELECTOR, limit));
const raw = await page.evaluate(buildFlightExtractJs(ROUND_CARD_SELECTOR, false));
if (!Array.isArray(raw)) {
throw new CommandExecutionError('Ctrip round-trip flight DOM extraction returned malformed rows');
}
if (raw.length === 0) {
if (Number(renderedCardCount) > 0) {
throw new CommandExecutionError('Ctrip round-trip flight cards rendered but parser did not find required flight anchors');
}
throw new EmptyResultError('ctrip flight-round', `No round-trip flights for ${fromCode}→${toCode} on ${depart} / ${ret}`);
}
const completeRows = raw
.filter((r) => r.departureTime && r.departureAirport && r.arrivalTime && r.arrivalAirport && r.airline)
.slice(0, limit)
.map((r, i) => ({
rank: i + 1,
airline: r.airline,
flightNo: r.flightNo,
aircraft: r.aircraft,
departureTime: r.departureTime,
departureAirport: r.departureAirport,
arrivalTime: r.arrivalTime,View on GitHub (pinned to 49907e53dc)
Solutions
- Retry — if it's a transient page mutation it may pass on rerun.
- Update to the latest library version in case a DOM-drift fix has shipped.
- Reproduce manually and file an issue with the wait state and page URL; this indicates parser breakage rather than bad input.
- If you control timing, ensure no other automation is navigating the same page concurrently.
Example fix
// before
const rows = await runFlightRound(args); // crashes on non-array
// after
let rows;
try { rows = await runFlightRound(args); } catch (e) {
if (String(e.message).includes('malformed rows')) rows = await runFlightRound(args); // retry once
else throw e;
} Defensive patterns
Strategy: retry
Type guard
function isMalformedRowsError(e) { return e && String(e.message || '').includes('malformed rows'); } Try / catch
try { return await runFlightRound(args); }
catch (e) { if (isMalformedRowsError(e)) { await sleep(5000); return await runFlightRound(args); } throw e; } Prevention
- Retry once on 'malformed rows' — often a transient page mutation.
- Avoid concurrent automation on the same browser session/page.
- Report persistent occurrences as parser breakage with URL and version.
- Pin the library version and test against Ctrip after announced UI changes.
When it happens
Trigger: buildFlightExtractJs evaluated in the page returns null/undefined or a non-array (e.g. an exception object or wrong shape) instead of an array of extracted flight rows.
Common situations: Ctrip DOM changed so the extraction script's return path changed; the evaluate() call was intercepted by a page error; internal scraper bug producing a non-array; page replaced content mid-extraction.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Ctrip round-trip flight cards rendered but parser did not fi
- Ctrip round-trip flight rows were missing required airline/f
- Ctrip cruise DOM extraction returned malformed rows
- Ctrip cruise cards rendered but parser did not find required
- Ctrip ferry DOM extraction returned malformed rows
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/a0c84bb7fe375aef.
Report an issue: GitHub.