jackwener/OpenCLI · error · CommandExecutionError
Trip.com hotel detail SSR extraction returned malformed data
Error message
Trip.com hotel detail SSR extraction returned malformed data
What it means
This CommandExecutionError is thrown when buildHotelDetailExtractJs() executed in the page but returned null or a non-object — the SSR data was present enough to pass the wait check, yet the extraction step could not produce a structured detail object. It indicates a mismatch between the extraction script and Trip.com's actual page payload.
Source
Thrown at clis/trip/hotel.js:47
'star', 'score', 'scoreLabel', 'reviewCount', 'ratingBreakdown',
'facilities', 'checkInOut',
'cityName', 'address', 'lat', 'lon',
'url',
],
func: async (page, kwargs) => {
const hotelId = parseHotelId('id', kwargs.id);
const url = buildHotelDetailUrl(hotelId);
await page.goto(url);
const waitResult = await page.evaluate(WAIT_FOR_HOTEL_DETAIL_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 hotel detail page did not expose SSR hotel data (state=${String(waitResult)})`);
}
const detail = await page.evaluate(buildHotelDetailExtractJs());
if (!detail || typeof detail !== 'object') {
throw new CommandExecutionError('Trip.com hotel detail SSR extraction returned malformed data');
}
if (!detail.hotelId || !detail.name) {
throw new EmptyResultError('trip hotel', `No detail exposed for hotel id ${hotelId}`);
}
return [{ ...detail, url }];
},
});
View on GitHub (pinned to 49907e53dc)
Solutions
- Retry — partial renders can pass the wait check before the payload is complete
- Inspect the page payload in a browser and update the extraction script to the new SSR shape
- Pin or update the library version matching the current Trip.com page structure
- Add a guard so early/partial renders trigger an explicit re-wait instead of extraction
Example fix
// before
const detail = await tripHotelDetail({ id }); // SSR shape changed, returns malformed
// after
// update library so buildHotelDetailExtractJs reads the new SSR key
const detail = await tripHotelDetail({ id }); // works with updated extractor Defensive patterns
Strategy: try-catch
Type guard
function isHotelDetail(d) {
return d !== null && typeof d === 'object' && !Array.isArray(d);
} Try / catch
try {
const detail = await tripHotelDetail({ id });
} catch (e) {
if (e instanceof CommandExecutionError && e.message.includes('malformed')) {
// extraction/schema mismatch — flag for extractor update, skip item
logger.warn({ hotelId: id }, 'trip SSR extraction failed');
return null;
}
throw e;
} Prevention
- Update the extractor whenever Trip.com changes its SSR payload shape
- Ensure page loads complete before extraction (don't bypass wait checks)
- Pin and test the library against the live page structure periodically
- Log the raw page state on failure to speed up diagnosing schema drift
When it happens
Trigger: page.evaluate(buildHotelDetailExtractJs()) returns null/undefined/a primitive because the expected SSR JSON structure changed, was truncated, or the extraction selectors no longer match the DOM.
Common situations: Trip.com renaming or reshaping its embedded SSR state, partial page renders where the wait heuristic passed early, or A/B-tested layouts lacking expected fields.
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 hotel detail SSR extraction returned malformed data
- Trip.com hotel detail page did not expose SSR hotel data (st
- No detail exposed for hotel id ${hotelId}
- Ctrip attraction DOM extraction returned malformed rows
- ctrip hotel-search
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/3e77a4098b89ea0f.
Report an issue: GitHub.