{"record":{"id":"38b40d76a4b0f4e6","repo":"jackwener/OpenCLI","slug":"trip-com-flight-page-did-not-render-flight-cards-38b40d","errorCode":null,"errorMessage":"Trip.com flight page did not render flight cards (state=${String(waitResult)})","messagePattern":"Trip\\.com flight page did not render flight cards \\(state=(.+?)\\)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/trip/flight.js","lineNumber":60,"sourceCode":"        'url',\n    ],\n    func: async (page, kwargs) => {\n        const fromCode = parseIataCode('from', kwargs.from);\n        const toCode = parseIataCode('to', kwargs.to);\n        if (fromCode === toCode) {\n            throw new ArgumentError(`--from and --to must differ (got ${fromCode})`);\n        }\n        const date = parseIsoDate('date', kwargs.date);\n        const limit = parseListLimit(kwargs.limit);\n\n        const searchUrl = buildFlightSearchUrl(fromCode, toCode, date);\n        await page.goto(searchUrl);\n        const waitResult = await page.evaluate(WAIT_FOR_FLIGHTS_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 flight page did not render flight cards (state=${String(waitResult)})`);\n        }\n        const raw = await page.evaluate(buildFlightExtractJs());\n        if (!Array.isArray(raw)) {\n            const reason = raw && typeof raw === 'object' && typeof raw.error === 'string'\n                && /^malformed flight card \\d+: [a-z /]+$/.test(raw.error)\n                ? `: ${raw.error}`\n                : '';\n            throw new CommandExecutionError(`Trip.com flight DOM extraction returned malformed rows${reason}`);\n        }\n        if (raw.length === 0) {\n            throw new EmptyResultError('trip flight', `No flights for ${fromCode} to ${toCode} on ${date}`);\n        }\n        return raw.slice(0, limit).map((r, i) => ({\n            rank: i + 1,\n            airline: r.airline,\n            departureTime: r.departureTime,\n            departureAirport: r.departureAirport,\n            arrivalTime: r.arrivalTime,","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/trip/flight.js#L42-L78","documentation":"This CommandExecutionError from clis/trip/flight.js is thrown when WAIT_FOR_FLIGHTS_JS returns anything other than 'content' (and not 'captcha'), meaning the Trip.com flight page loaded but never reached a state with rendered flight cards. The message includes the observed state string to help diagnose what the waiter saw. It indicates a page-load/render/timing problem rather than empty results or a CAPTCHA.","triggerScenarios":"page.evaluate(WAIT_FOR_FLIGHTS_JS) after page.goto(searchUrl) returns e.g. 'timeout', 'error', or any non-'content' value, with no CAPTCHA detected.","commonSituations":"Slow network or throttled page load exceeding the waiter's timeout; Trip.com layout change breaking the flight-card selector; JavaScript disabled or failing in the headless browser; regional redirects to pages the waiter does not recognize.","solutions":["Read the state value in the message and rerun with a longer wait timeout if it indicates a timeout.","Open the same search URL in a visible browser to check whether flight cards render at all.","Update WAIT_FOR_FLIGHTS_JS selectors if Trip.com changed its DOM structure.","Retry later or from a different network/region if the page loads incompletely."],"exampleFix":"// before\nawait page.goto(url);\nconst r = await page.evaluate(WAIT_FOR_FLIGHTS_JS); // 'timeout' -> CommandExecutionError\n// after\nawait page.goto(url, { waitUntil: 'networkidle2' });\nconst r = await page.evaluate(WAIT_FOR_FLIGHTS_JS);\nif (r !== 'content') {\n  await page.waitForSelector(FLIGHT_CARD_SELECTOR, { timeout: 30000 }).catch(() => {});\n  r = await page.evaluate(WAIT_FOR_FLIGHTS_JS);\n}","handlingStrategy":"retry","validationCode":"// Confirm the search URL is well-formed before invoking:\nif (!/^https:\\/\\/\\S*trip\\.com\\/.+/.test(buildFlightSearchUrl(from, to, date))) throw new Error('unexpected search URL');\nif (isNaN(new Date(date))) throw new Error('date must be ISO');","typeGuard":"const isCommandExecutionError = (e) => e instanceof CommandExecutionError;","tryCatchPattern":"try {\n  await runTripFlight(args);\n} catch (e) {\n  if (isCommandExecutionError(e) && /state=timeout/.test(e.message)) {\n    await sleep(5000);\n    return runTripFlightWithLongerTimeout(args, 30000); // one bounded retry\n  }\n  throw e; // non-timeout states (layout changes) need a fix, not a retry\n}","preventionTips":["Parse the state= value from the message to choose retry vs. fix.","Use generous timeouts; hotel/flight pages are heavy.","Keep WAIT_FOR_FLIGHTS_JS selectors updated against Trip.com layout changes.","Log the failing URL and state for reproducibility."],"tags":["scraping","timeout","dom-render","trip-com","flights"],"backgroundTag":"page-render-timeout","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}