jackwener/OpenCLI · error · CommandExecutionError
Trip.com tour search returned malformed data
Error message
Trip.com tour search returned malformed data
What it means
This CommandExecutionError is thrown when the in-page tour-search script returns null or a non-object, meaning the browser automation could not extract the expected structured result from the Trip.com tours page. It indicates the page did not run/complete the embedded extraction JS as designed — a page-level failure, not an empty search.
Source
Thrown at clis/trip/tour.js:56
{ name: 'limit', type: 'int', default: 20, help: 'Number of tours (1-50)' },
],
columns: [
'rank',
'name', 'type',
'rating', 'reviews',
'price', 'currency',
'url',
],
func: async (page, kwargs) => {
const query = parseKeyword('query', kwargs.query);
const tourType = parseTourType(kwargs.type);
const limit = parseListLimit(kwargs.limit);
const searchUrl = buildTourSearchUrl(query, tourType);
await page.goto(searchUrl);
const result = await page.evaluate(buildTourSearchJs(query));
if (!result || typeof result !== 'object') {
throw new CommandExecutionError('Trip.com tour search returned malformed data');
}
if (result.status === 'captcha') {
throw new AuthRequiredError('trip.com', 'Trip.com is asking for a verification; complete it in your browser session and retry');
}
if (result.status === 'empty') {
throw new EmptyResultError('trip tour', `No ${kwargs.type || 'private'} tours for "${query}"`);
}
if (result.status !== 'content') {
throw new CommandExecutionError(`Trip.com tour search did not return results (state=${String(result.status)})`);
}
// Products captured but none carry a name is drift (schema moved), not an empty search;
// a genuine no-match resolves as status 'empty' above off the page's "0 routes found".
const rows = Array.isArray(result.rows) ? result.rows.filter((r) => r.name) : [];
if (rows.length === 0) {
throw new CommandExecutionError('Trip.com tour search captured products but none carried a name (the product markup may have changed)');
}
return rows.slice(0, limit).map((r, i) => ({
rank: i + 1,View on GitHub (pinned to 49907e53dc)
Solutions
- Retry the search — transient page-load failures often resolve on a second attempt.
- Increase any page load/timeout budgets so the tours page fully renders before evaluation.
- Manually open the built searchUrl in a browser to see what the page actually shows (redirect, consent wall, error page).
- Update buildTourSearchJs if the site changed structure or entry behavior.
Example fix
// before
const result = await page.goto(searchUrl); // no wait
const r = await page.evaluate(buildTourSearchJs(query));
// after
await page.goto(searchUrl, { waitUntil: 'networkidle' });
const r = await page.evaluate(buildTourSearchJs(query)); Defensive patterns
Strategy: retry
Validate before calling
// preflight: ensure the browser session is alive and the URL is reachable
const resp = await fetch(searchUrl, { method: 'HEAD' }).catch(() => null);
if (!resp || !resp.ok) throw new Error('Trip.com tours page unreachable before automation'); Type guard
function isSearchResult(r) { return r !== null && typeof r === 'object' && !Array.isArray(r); } Try / catch
try {
const rows = await tourSearch(query, type);
} catch (e) {
if (/malformed data/.test(e.message)) {
await sleep(2000);
return tourSearch(query, type); // single retry
}
throw e;
} Prevention
- Use waitUntil: 'networkidle' (or equivalent) before evaluating page scripts.
- Keep the browser session healthy; avoid navigating mid-extraction.
- Add a bounded retry with backoff around browser-automation searches.
- Watch for regional redirects/consent pages and handle them before extraction.
When it happens
Trigger: page.evaluate(buildTourSearchJs(query)) returning undefined/null or a primitive — e.g. the extraction script threw inside the page, the page navigated away/redirected, or the DOM the script expects never rendered.
Common situations: Slow network so the page never reached the expected state; Trip.com redirecting to a different regional domain or consent page; the extraction script's entry-point selector disappearing after a site update.
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
- Failed to fetch Barchart greeks for ${symbol}
- Failed to extract Booking.com cards: ${err?.message || err}
- Booking.com page returned no extractable data
- Booking.com extractor returned an invalid status
- Booking.com extractor returned malformed items
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/4062f15af525c840.
Report an issue: GitHub.