{"record":{"id":"3e77a4098b89ea0f","repo":"jackwener/OpenCLI","slug":"trip-com-hotel-detail-ssr-extraction-returned-malf","errorCode":null,"errorMessage":"Trip.com hotel detail SSR extraction returned malformed data","messagePattern":"Trip\\.com hotel detail SSR extraction returned malformed data","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/trip/hotel.js","lineNumber":47,"sourceCode":"        'star', 'score', 'scoreLabel', 'reviewCount', 'ratingBreakdown',\n        'facilities', 'checkInOut',\n        'cityName', 'address', 'lat', 'lon',\n        'url',\n    ],\n    func: async (page, kwargs) => {\n        const hotelId = parseHotelId('id', kwargs.id);\n        const url = buildHotelDetailUrl(hotelId);\n        await page.goto(url);\n        const waitResult = await page.evaluate(WAIT_FOR_HOTEL_DETAIL_JS);\n        if (waitResult === 'captcha') {\n            throw new AuthRequiredError('trip.com', 'Trip.com is asking for a verification; complete it in your browser session and retry');\n        }\n        if (waitResult !== 'content') {\n            throw new CommandExecutionError(`Trip.com hotel detail page did not expose SSR hotel data (state=${String(waitResult)})`);\n        }\n        const detail = await page.evaluate(buildHotelDetailExtractJs());\n        if (!detail || typeof detail !== 'object') {\n            throw new CommandExecutionError('Trip.com hotel detail SSR extraction returned malformed data');\n        }\n        if (!detail.hotelId || !detail.name) {\n            throw new EmptyResultError('trip hotel', `No detail exposed for hotel id ${hotelId}`);\n        }\n        return [{ ...detail, url }];\n    },\n});\n","sourceCodeStart":29,"sourceCodeEnd":55,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/trip/hotel.js#L29-L55","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nconst detail = await tripHotelDetail({ id }); // SSR shape changed, returns malformed\n// after\n// update library so buildHotelDetailExtractJs reads the new SSR key\nconst detail = await tripHotelDetail({ id }); // works with updated extractor","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isHotelDetail(d) {\n  return d !== null && typeof d === 'object' && !Array.isArray(d);\n}","tryCatchPattern":"try {\n  const detail = await tripHotelDetail({ id });\n} catch (e) {\n  if (e instanceof CommandExecutionError && e.message.includes('malformed')) {\n    // extraction/schema mismatch — flag for extractor update, skip item\n    logger.warn({ hotelId: id }, 'trip SSR extraction failed');\n    return null;\n  }\n  throw e;\n}","preventionTips":["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"],"tags":["scraping","ssr","extraction","trip-com","schema-changed"],"backgroundTag":"dom-selector-mismatch","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}