jackwener/OpenCLI · error · CommandExecutionError
Ctrip hotel detail SSR extraction returned malformed data
Error message
Ctrip hotel detail SSR extraction returned malformed data
What it means
CommandExecutionError thrown when the SSR extraction step returns null or a non-object even though the page reached the 'content' state. The wait script said content was ready, but buildHotelDetailExtractJs() failed to assemble a detail object, indicating the DOM nodes it reads exist but its data assembly broke.
Source
Thrown at clis/ctrip/hotel.js:49
'star', 'score', 'scoreLabel', 'reviewCount', 'ratingBreakdown',
'facilities', 'checkInOut',
'cityName', 'address', 'lat', 'lon',
'url',
],
func: async (page, kwargs) => {
const hotelId = parseHotelId(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('hotels.ctrip.com', 'Ctrip is asking for a captcha; complete it in your browser session and retry');
}
if (waitResult !== 'content') {
throw new CommandExecutionError(`Ctrip 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('Ctrip hotel detail SSR extraction returned malformed data');
}
if (!detail.hotelId || !detail.name) {
throw new EmptyResultError('ctrip hotel', `No detail exposed for hotel id ${hotelId}`);
}
return [{ ...detail, url }];
},
});
View on GitHub (pinned to 49907e53dc)
Solutions
- Add a short delay or wait for the detail data node before running buildHotelDetailExtractJs()
- Log the raw extraction output and update buildHotelDetailExtractJs to current markup
- Update the CLI to the latest version
- Wrap extraction in try/catch inside the page and return diagnostics
Example fix
// before
const detail = await page.evaluate(buildHotelDetailExtractJs());
if (!detail || typeof detail !== 'object') throw new CommandExecutionError('...malformed data');
// after
await page.waitForSelector(DETAIL_DATA_SELECTOR, { timeout: 10000 });
const detail = await page.evaluate(buildHotelDetailExtractJs());
if (!detail || typeof detail !== 'object') throw new CommandExecutionError('...malformed data'); Defensive patterns
Strategy: try-catch
Validate before calling
await page.waitForSelector(DETAIL_DATA_SELECTOR, { timeout: 10000 }); // ensure data node exists before extracting
const detail = await page.evaluate(buildHotelDetailExtractJs());
if (!detail || typeof detail !== 'object') throw new Error('detail extraction malformed'); Type guard
const isDetailObject = (v) => !!v && typeof v === 'object' && !Array.isArray(v);
Try / catch
try {
return await ctrip.hotel({ id });
} catch (e) {
if (e instanceof CommandExecutionError && /malformed data/.test(e.message)) {
// hydration race: wait longer and retry once, else escalate as markup drift
await sleep(3000);
return await ctrip.hotel({ id });
}
throw e;
} Prevention
- Wait for the detail data node, not just the content shell, before extracting
- Log the raw extraction result on failure
- Keep the extract script updated against current markup
- Detect repeated malformed extractions as a page-structure change signal
When it happens
Trigger: buildHotelDetailExtractJs() evaluates to null/undefined/a primitive: the detail container renders but inner data blocks it reads are absent (partial render, hydration race), or the script throws internally and page.evaluate surfaces null.
Common situations: Ctrip hydrating detail data client-side after the extract runs; regional page variants missing fields the extract script reads; Ctrip markup update after the wait selector still matched; corrupted/partial page load on flaky networks.
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 hotel detail SSR extraction returned malformed data
- ctrip hotel-search
- Ctrip hotel detail page did not expose SSR hotel data (state
- LinkedIn job detail returned malformed extraction payload
- LinkedIn job detail could not find a job title
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/c83c3c44e98679bb.
Report an issue: GitHub.