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

  1. Retry — if it's a transient page mutation it may pass on rerun.
  2. Update to the latest library version in case a DOM-drift fix has shipped.
  3. Reproduce manually and file an issue with the wait state and page URL; this indicates parser breakage rather than bad input.
  4. 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

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

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/a0c84bb7fe375aef. Report an issue: GitHub.