{"record":{"id":"8317041d2dad5671","repo":"jackwener/OpenCLI","slug":"no-sailings-for-fromcity-to-tocity-on-date","errorCode":null,"errorMessage":"No sailings for ${fromCity} to ${toCity} on ${date}","messagePattern":"No sailings for (.+?) to (.+?) on (.+?)","errorType":"exception","errorClass":"EmptyResultError","httpStatus":null,"severity":"warning","filePath":"clis/ctrip/ferry.js","lineNumber":72,"sourceCode":"        const searchUrl = buildFerryListUrl(fromCity, toCity, date);\n        await page.goto(searchUrl);\n        const waitResult = await page.evaluate(WAIT_FOR_FERRY_JS);\n        if (waitResult === 'captcha') {\n            throw new AuthRequiredError('ship.ctrip.com', 'Ctrip is asking for a captcha; complete it in your browser session and retry');\n        }\n        if (waitResult !== 'content') {\n            throw new CommandExecutionError(`Ctrip ferry page did not render sailing rows (state=${String(waitResult)})`);\n        }\n        const renderedCardCount = await page.evaluate(buildScrollUntilJs('.list-item-parent', limit));\n        const raw = await page.evaluate(buildFerryExtractJs());\n        if (!Array.isArray(raw)) {\n            throw new CommandExecutionError('Ctrip ferry DOM extraction returned malformed rows');\n        }\n        if (raw.length === 0) {\n            if (Number(renderedCardCount) > 0) {\n                throw new CommandExecutionError('Ctrip ferry rows rendered but parser did not find required sailing anchors');\n            }\n            throw new EmptyResultError('ctrip ferry', `No sailings for ${fromCity} to ${toCity} on ${date}`);\n        }\n        return raw.slice(0, limit).map((r, i) => ({\n            rank: i + 1,\n            shipName: r.shipName,\n            departureTime: r.departureTime,\n            fromPort: r.fromPort,\n            arrivalTime: r.arrivalTime,\n            toPort: r.toPort,\n            duration: r.duration,\n            price: r.price,\n            status: r.status,\n            url: searchUrl,\n        }));\n    },\n});\n","sourceCodeStart":54,"sourceCodeEnd":88,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/ctrip/ferry.js#L54-L88","documentation":"This is thrown as an EmptyResultError by the Ctrip ferry CLI when DOM scraping completed successfully but the parsed sailing-rows array is empty. The library distinguishes a genuine 'no sailings' result from a parse failure: if cards were rendered but rows could not be parsed, a different CommandExecutionError is thrown instead, so this error means the page genuinely listed zero sailings for the requested city pair and date.","triggerScenarios":"Running the `ctrip ferry` command with a from/to city pair and date on which Ctrip's ferry search page renders zero sailing cards, and renderedCardCount is 0 (or falsy) so the empty result is legitimate.","commonSituations":"Searching an off-season date or a route that is suspended; misspelling city names so Ctrip resolves no routes; querying a same-day date after all sailings have departed; picking a route Ctrip does not sell (e.g. ferry vs. bus substituted).","solutions":["Double-check the city names and confirm the route is actually served by a ferry on that date on the Ctrip site.","Retry with a nearby date to confirm availability is the issue rather than a route/data problem.","Catch EmptyResultError in your script and treat it as an expected empty result (exit code EMPTY_RESULT), not a crash.","If sailings clearly exist on the site, report a possible DOM/parser drift issue to the maintainers."],"exampleFix":"// before\ncli(['ferry', '--from', 'Shanghai', '--to', 'Shengsi', '--date', '2026-01-05']);\n// after\ntry {\n  cli(['ferry', '--from', 'Shanghai', '--to', 'Shengsi', '--date', '2026-01-05']);\n} catch (e) {\n  if (e instanceof EmptyResultError) console.log('no sailings that day');\n  else throw e;\n}","handlingStrategy":"try-catch","validationCode":"const valid = from && to && /^\\d{4}-\\d{2}-\\d{2}$/.test(date) && new Date(date) >= new Date(new Date().toDateString());\nif (!valid) throw new Error('check route/city names and use a current-or-future date');","typeGuard":"function isEmptyResultError(e) { return e && typeof e.code === 'string' && e.code === 'EMPTY_RESULT'; }","tryCatchPattern":"try { const sailings = await cli(['ferry','--from',from,'--to',to,'--date',date]); return sailings; }\ncatch (e) { if (e instanceof EmptyResultError || e.code === 'EMPTY_RESULT') return []; throw e; }","preventionTips":["Verify the route and date exist on Ctrip's site before automating it.","Treat EMPTY_RESULT exit code as an expected outcome in scripts.","Search a date range instead of a single date when availability is uncertain.","Keep city names canonical (as Ctrip resolves them) to avoid zero-match searches."],"tags":["empty-result","scraping","ctrip","ferry"],"backgroundTag":"empty-result-set","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}