{"record":{"id":"5ccbfce278fc8ff1","repo":"jackwener/OpenCLI","slug":"no-cruises-currently-departing-port","errorCode":null,"errorMessage":"No cruises currently departing \"${port}\"","messagePattern":"No cruises currently departing \"(.+?)\"","errorType":"exception","errorClass":"EmptyResultError","httpStatus":null,"severity":"info","filePath":"clis/ctrip/cruise.js","lineNumber":71,"sourceCode":"        }\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') {\n                throw new CommandExecutionError(`Ctrip cruise port page did not render (state=${String(portWait)})`);\n            }\n        }\n\n        const raw = await page.evaluate(buildCruiseExtractJs());\n        if (!Array.isArray(raw)) {\n            throw new CommandExecutionError('Ctrip cruise DOM extraction returned malformed rows');\n        }\n        if (raw.length === 0) {\n            throw new CommandExecutionError('Ctrip cruise cards rendered but parser did not find required itinerary anchors');\n        }\n        return raw.slice(0, limit).map((r, i) => ({\n            rank: i + 1,\n            title: r.title,\n            star: r.star,\n            boarding: r.boarding,","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/ctrip/cruise.js#L53-L89","documentation":"EmptyResultError thrown when the port's cruise.ctrip.com results page renders successfully but the WAIT_FOR_CRUISE_JS probe reports state 'empty' — the page explicitly indicates no cruise itineraries exist for that departure port. This is a semantic empty result, distinct from a rendering failure or captcha, and signals the requested port is valid but currently has no listed departures.","triggerScenarios":"Calling `ctrip cruise <port>` where the resolved port's sN results page loads and renders its 'no products' state, i.e. no `.route_info` cards would ever appear. Note it is only checked on the non-index branch (portCode !== '2'), so a genuinely empty Shanghai port page would instead surface as the parser-missing-anchors error.","commonSituations":"Querying a small/inland port that seasonally (or permanently) has no cruise departures; searching for a port name that resolves to a real but inactive port code; schedules temporarily withdrawn during off-season or after schedule changes.","solutions":["Retry with a major listed sea-cruise port such as 上海 / 威尼斯 / 罗马 to confirm the command works","Check the port page in a browser to confirm Ctrip truly lists no departures for it","Pick a nearby larger port as the departure point instead","If the port should have sailings, verify the resolved port name is spelled exactly as Ctrip lists it"],"exampleFix":"// before: query may hit an empty seasonal port\nawait run(['ctrip', 'cruise', '三亚']);\n// after: fall back to a major hub port\ntry {\n  await run(['ctrip', 'cruise', '三亚']);\n} catch (e) {\n  if (e.name === 'EmptyResultError') {\n    await run(['ctrip', 'cruise', '上海']);\n  } else throw e;\n}","handlingStrategy":"fallback","validationCode":"// Pre-validate the port against Ctrip's listed index before searching departures\nconst portCode = await page.goto(indexUrl).then(() => page.evaluate(buildCruisePortLookupJs(port)));\nif (!portCode) throw new Error(`Unknown port: ${port}`);","typeGuard":"function isEmptyResultError(e) {\n  return e instanceof Error && e.name === 'EmptyResultError';\n}","tryCatchPattern":"try {\n  return await run(['ctrip', 'cruise', port]);\n} catch (e) {\n  if (isEmptyResultError(e)) {\n    return fallbackPorts.map(p => run(['ctrip', 'cruise', p])); // e.g. 上海, 威尼斯, 罗马\n  }\n  throw e;\n}","preventionTips":["Prefer major hub ports (上海 / 威尼斯 / 罗马) that reliably list departures","Treat EmptyResultError as data, not failure — log and continue in batch jobs","Check the port page in a browser for seasonal schedule gaps before relying on it","Validate the port name spelling matches Ctrip's listed port names exactly"],"tags":["empty-result","ctrip","cruise","no-data"],"backgroundTag":"empty-search-results","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}