jackwener/OpenCLI · error · CommandExecutionError
Trip.com train DOM extraction returned malformed rows
Error message
Trip.com train DOM extraction returned malformed rows
What it means
CommandExecutionError thrown when page.evaluate(buildTrainExtractJs()) returns a non-array. The wait probe said 'content' (results rendered), but the extraction script came back in an unexpected shape, meaning the DOM structure changed or the script was sabotaged by page code.
Source
Thrown at clis/trip/train.js:60
],
func: async (page, kwargs) => {
const from = parseKeyword('from', kwargs.from);
const to = parseKeyword('to', kwargs.to);
const country = parseKeyword('country', kwargs.country);
const limit = parseListLimit(kwargs.limit);
const searchUrl = buildTrainRouteUrl(country, from, to);
await page.goto(searchUrl);
const waitResult = await page.evaluate(WAIT_FOR_TRAINS_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 train timetable did not render (state=${String(waitResult)}); check the city names and --country`);
}
const raw = await page.evaluate(buildTrainExtractJs());
if (!Array.isArray(raw)) {
throw new CommandExecutionError('Trip.com train DOM extraction returned malformed rows');
}
if (raw.length === 0) {
throw new EmptyResultError('trip train', `No timetable for ${from} to ${to} (${country})`);
}
return raw.slice(0, limit).map((r, i) => ({
rank: i + 1,
departureTime: r.departureTime,
fromStation: r.fromStation,
arrivalTime: r.arrivalTime,
toStation: r.toStation,
duration: r.duration,
changes: r.changes,
url: searchUrl,
}));
},
});
View on GitHub (pinned to 49907e53dc)
Solutions
- Update buildTrainExtractJs() selectors to match the current Trip.com train-card markup
- Log the raw evaluate result to see the actual shape returned
- Pin or bypass A/B test variants (cookies/URL params) so the stable layout renders
- Add a defensive Array.isArray check with diagnostics upstream of this throw
Example fix
// before
const raw = await page.evaluate(buildTrainExtractJs());
if (!Array.isArray(raw)) throw new CommandExecutionError('malformed rows');
// after
const raw = await page.evaluate(buildTrainExtractJs());
if (!Array.isArray(raw)) {
console.error('extract returned:', raw);
throw new CommandExecutionError('malformed rows: ' + JSON.stringify(raw).slice(0, 200));
} Defensive patterns
Strategy: type-guard
Validate before calling
// cannot pre-validate; guard the result instead
const raw = await page.evaluate(buildTrainExtractJs());
if (raw == null) throw new Error('extract returned null — selector drift likely'); Type guard
function isTrainRows(v) {
return Array.isArray(v) && v.every(r =>
r && typeof r.departureTime === 'string' && typeof r.fromStation === 'string');
} Try / catch
try {
const rows = await getTripTrains(args);
} catch (e) {
if (e instanceof CommandExecutionError && e.message.includes('malformed rows')) {
console.error('Trip.com DOM changed; capture page HTML for selector update');
}
throw e;
} Prevention
- Pin test snapshots of the extractor output in CI
- Monitor Trip.com markup changes; alert on this error
- Log the raw evaluate result alongside the throw
- Keep extraction selectors centralized for quick patching
When it happens
Trigger: Trip.com renders train rows in a new DOM structure so buildTrainExtractJs() returns null/an object instead of an array; a page-side script overwrites the expected global; or the evaluate result fails to serialize as an array.
Common situations: Trip.com frontend redesign/A-B test changing row markup; extraction script pinned to old class names; headless browser returning undefined because of a serialization issue in the evaluate payload.
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 transfer DOM extraction returned malformed rows
- 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
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/83143a67dff58f51.
Report an issue: GitHub.