jackwener/OpenCLI · info · EmptyResultError
No cruises currently departing "${port}"
Error message
No cruises currently departing "${port}" What it means
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.
Source
Thrown at clis/ctrip/cruise.js:71
}
if (indexWait !== 'content') {
throw new CommandExecutionError(`Ctrip cruise page did not render (state=${String(indexWait)})`);
}
const portCode = await page.evaluate(buildCruisePortLookupJs(port));
if (!portCode) {
throw new EmptyResultError('ctrip cruise', `No cruise departure port matching "${port}" (try a listed sea-cruise port like 上海 / 威尼斯 / 罗马)`);
}
let searchUrl = indexUrl;
if (portCode !== PORT_INDEX_CODE) {
searchUrl = buildCruiseSearchUrl(portCode);
await page.goto(searchUrl);
const portWait = await page.evaluate(WAIT_FOR_CRUISE_JS);
if (portWait === 'captcha') {
throw new AuthRequiredError('cruise.ctrip.com', 'Ctrip is asking for a captcha; complete it in your browser session and retry');
}
if (portWait === 'empty') {
throw new EmptyResultError('ctrip cruise', `No cruises currently departing "${port}"`);
}
if (portWait !== 'content') {
throw new CommandExecutionError(`Ctrip cruise port page did not render (state=${String(portWait)})`);
}
}
const raw = await page.evaluate(buildCruiseExtractJs());
if (!Array.isArray(raw)) {
throw new CommandExecutionError('Ctrip cruise DOM extraction returned malformed rows');
}
if (raw.length === 0) {
throw new CommandExecutionError('Ctrip cruise cards rendered but parser did not find required itinerary anchors');
}
return raw.slice(0, limit).map((r, i) => ({
rank: i + 1,
title: r.title,
star: r.star,
boarding: r.boarding,View on GitHub (pinned to 49907e53dc)
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
Example fix
// before: query may hit an empty seasonal port
await run(['ctrip', 'cruise', '三亚']);
// after: fall back to a major hub port
try {
await run(['ctrip', 'cruise', '三亚']);
} catch (e) {
if (e.name === 'EmptyResultError') {
await run(['ctrip', 'cruise', '上海']);
} else throw e;
} Defensive patterns
Strategy: fallback
Validate before calling
// Pre-validate the port against Ctrip's listed index before searching departures
const portCode = await page.goto(indexUrl).then(() => page.evaluate(buildCruisePortLookupJs(port)));
if (!portCode) throw new Error(`Unknown port: ${port}`); Type guard
function isEmptyResultError(e) {
return e instanceof Error && e.name === 'EmptyResultError';
} Try / catch
try {
return await run(['ctrip', 'cruise', port]);
} catch (e) {
if (isEmptyResultError(e)) {
return fallbackPorts.map(p => run(['ctrip', 'cruise', p])); // e.g. 上海, 威尼斯, 罗马
}
throw e;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- No coaches for ${fromCity} to ${toCity} on ${date}
- No cruise departure port matching "${port}" (try a listed se
- No trains found from ${fromStation.name} to ${toStation.name
- NO_DATA
- No Wayback snapshots for "${target}".
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/5ccbfce278fc8ff1.
Report an issue: GitHub.