jackwener/OpenCLI · error · CommandExecutionError
Trip.com flight DOM extraction returned malformed rows${reas
Error message
Trip.com flight DOM extraction returned malformed rows${reason} What it means
This CommandExecutionError from clis/trip/flight.js is thrown when buildFlightExtractJs() returns a non-array, meaning the in-page extractor found flight-card-like elements but failed to parse at least one row into a clean object. When the returned object carries an error string matching /^malformed flight card \d+: [a-z /]+$/, that per-card reason is appended to the message. It signals a DOM structure change or unexpected card content, not an empty page.
Source
Thrown at clis/trip/flight.js:68
const date = parseIsoDate('date', kwargs.date);
const limit = parseListLimit(kwargs.limit);
const searchUrl = buildFlightSearchUrl(fromCode, toCode, date);
await page.goto(searchUrl);
const waitResult = await page.evaluate(WAIT_FOR_FLIGHTS_JS);
if (waitResult === 'captcha') {
throw new AuthRequiredError('trip.com', 'Trip.com is asking for a verification; complete it in your browser session and retry');
}
if (waitResult !== 'content') {
throw new CommandExecutionError(`Trip.com flight page did not render flight cards (state=${String(waitResult)})`);
}
const raw = await page.evaluate(buildFlightExtractJs());
if (!Array.isArray(raw)) {
const reason = raw && typeof raw === 'object' && typeof raw.error === 'string'
&& /^malformed flight card \d+: [a-z /]+$/.test(raw.error)
? `: ${raw.error}`
: '';
throw new CommandExecutionError(`Trip.com flight DOM extraction returned malformed rows${reason}`);
}
if (raw.length === 0) {
throw new EmptyResultError('trip flight', `No flights for ${fromCode} to ${toCode} on ${date}`);
}
return raw.slice(0, limit).map((r, i) => ({
rank: i + 1,
airline: r.airline,
departureTime: r.departureTime,
departureAirport: r.departureAirport,
arrivalTime: r.arrivalTime,
arrivalAirport: r.arrivalAirport,
duration: r.duration,
stops: r.stops,
price: r.price,
currency: r.currency,
url: searchUrl,
}));
},View on GitHub (pinned to 49907e53dc)
Solutions
- Read the appended reason (if any) to see which card and field was malformed.
- Open the page in a browser and inspect the flight card DOM for layout changes.
- Update buildFlightExtractJs() field selectors to match the current markup.
- Add defensive field extraction (defaulting missing fields) so a single odd card does not abort the whole extraction, then retry.
Example fix
// before
throw new CommandExecutionError(`...malformed rows${reason}`);
// after
if (!Array.isArray(raw)) {
console.warn('extraction returned', raw);
raw = []; // or skip malformed cards inside buildFlightExtractJs
}
throw new CommandExecutionError(`...malformed rows${reason}`); // only when unrecoverable Defensive patterns
Strategy: type-guard
Validate before calling
// Cannot pre-validate server DOM; verify library/site assumptions after upgrade:
const smoke = await runTripFlight({ from: 'SFO', to: 'LAX', date: nextFriday(), limit: 1 });
if (!Array.isArray(smoke)) throw new Error('extractor contract broken'); Type guard
const isExtractFailure = (e) => e instanceof CommandExecutionError && /malformed rows/.test(e.message); const isArrayPayload = (v) => Array.isArray(v);
Try / catch
try {
const flights = await runTripFlight(args);
} catch (e) {
if (isExtractFailure(e)) {
console.error(`Trip.com DOM may have changed: ${e.message}`);
return null; // degrade gracefully, alert maintainers
}
throw e;
} Prevention
- Include the extractor's raw.error reason in monitoring alerts.
- Make in-page extractors skip malformed cards instead of failing whole extraction.
- Re-run a smoke search after Trip.com releases UI changes.
- Keep extraction selectors centralized and easily updatable.
When it happens
Trigger: page.evaluate(buildFlightExtractJs()) returns null, an object like { error: 'malformed flight card 3: missing airline' }, or any non-array because one or more flight cards lacked expected fields/shape.
Common situations: Trip.com A/B-testing a new flight card layout; ads or sponsored cards injected into the results list with different markup; partially rendered cards missing airline/time nodes when the extractor runs; regional variants of the site with different DOM.
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
- Trip.com attraction DOM extraction returned malformed rows
- Trip.com car DOM extraction returned malformed rows
- Trip.com car cards rendered but parser did not find required
- Trip.com deals page did not render deal tiles (state=${Strin
- Trip.com deals DOM extraction returned malformed rows
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/9ddca788eb88f751.
Report an issue: GitHub.