{"record":{"id":"96f6d1dff9fa4a04","repo":"jackwener/OpenCLI","slug":"ctrip-cruise-page-did-not-render-state-string-i","errorCode":null,"errorMessage":"Ctrip cruise page did not render (state=${String(indexWait)})","messagePattern":"Ctrip cruise page did not render \\(state=(.+?)\\)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/ctrip/cruise.js","lineNumber":55,"sourceCode":"    columns: [\n        'rank',\n        'title', 'star',\n        'boarding', 'sailingDate',\n        'tags', 'price',\n        'url',\n    ],\n    func: async (page, kwargs) => {\n        const port = parsePlaceName('port', kwargs.port);\n        const limit = parseListLimit(kwargs.limit);\n\n        const indexUrl = buildCruiseSearchUrl(PORT_INDEX_CODE);\n        await page.goto(indexUrl);\n        const indexWait = await page.evaluate(WAIT_FOR_CRUISE_JS);\n        if (indexWait === 'captcha') {\n            throw new AuthRequiredError('cruise.ctrip.com', 'Ctrip is asking for a captcha; complete it in your browser session and retry');\n        }\n        if (indexWait !== 'content') {\n            throw new CommandExecutionError(`Ctrip cruise page did not render (state=${String(indexWait)})`);\n        }\n        const portCode = await page.evaluate(buildCruisePortLookupJs(port));\n        if (!portCode) {\n            throw new EmptyResultError('ctrip cruise', `No cruise departure port matching \"${port}\" (try a listed sea-cruise port like 上海 / 威尼斯 / 罗马)`);\n        }\n\n        let searchUrl = indexUrl;\n        if (portCode !== PORT_INDEX_CODE) {\n            searchUrl = buildCruiseSearchUrl(portCode);\n            await page.goto(searchUrl);\n            const portWait = await page.evaluate(WAIT_FOR_CRUISE_JS);\n            if (portWait === 'captcha') {\n                throw new AuthRequiredError('cruise.ctrip.com', 'Ctrip is asking for a captcha; complete it in your browser session and retry');\n            }\n            if (portWait === 'empty') {\n                throw new EmptyResultError('ctrip cruise', `No cruises currently departing \"${port}\"`);\n            }\n            if (portWait !== 'content') {","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/ctrip/cruise.js#L37-L73","documentation":"The cruise index page is valid only when WAIT_FOR_CRUISE_JS returns 'content'. Any other non-captcha state means the page never rendered as expected, so the CLI throws CommandExecutionError with the state value embedded for diagnosis.","triggerScenarios":"`clis ctrip cruise` where page.evaluate(WAIT_FOR_CRUISE_JS) returns an unrecognized state (timeout, error variant, redirect target) on the cruise index URL.","commonSituations":"Slow network hitting the wait timeout; cruise.ctrip.com layout change so wait selectors no longer match; regional redirect to a different domain/variant; server-side error page.","solutions":["Retry the command — transient network slowness is a common cause","Inspect the `state=` value and align WAIT_FOR_CRUISE_JS states/selectors with the live page","Extend the wait timeout in WAIT_FOR_CRUISE_JS","Check whether cruise.ctrip.com redirects in your region and handle that URL"],"exampleFix":"null","handlingStrategy":"retry","validationCode":"null","typeGuard":"null","tryCatchPattern":"try {\n  cruises = await ctripCruiseList({ port });\n} catch (e) {\n  if (e instanceof CommandExecutionError && e.message.includes('did not render')) {\n    const state = /state=(\\S+)/.exec(e.message)?.[1];\n    console.error(`Cruise page wait failed (state=${state}); retrying`);\n    await sleep(3000);\n    cruises = await ctripCruiseList({ port });\n  } else {\n    throw e;\n  }\n}","preventionTips":["Retry with backoff; transient slow renders are the most common trigger","Log the `state=` value embedded in the message","Keep WAIT_FOR_CRUISE_JS selectors and timeout current with cruise.ctrip.com","Check for regional redirects to unexpected domains"],"tags":["dom-render","ctrip","timeout","scraping"],"backgroundTag":"page-did-not-render-expected-content","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}