jackwener/OpenCLI · warning · EmptyResultError

No coaches for ${fromCity} to ${toCity} on ${date}

Error message

No coaches for ${fromCity} to ${toCity} on ${date}

What it means

The page loaded fine, no captcha appeared, and the extractor returned an empty array with zero rendered cards — Ctrip genuinely has no bus departures for the requested route/date. The CLI throws EmptyResultError so the caller can distinguish 'no data' from 'scraping failed'.

Source

Thrown at clis/ctrip/bus.js:72

        const searchUrl = buildBusListUrl(fromCity, toCity, date);
        await page.goto(searchUrl);
        const waitResult = await page.evaluate(WAIT_FOR_BUS_JS);
        if (waitResult === 'captcha') {
            throw new AuthRequiredError('bus.ctrip.com', 'Ctrip is asking for a captcha; complete it in your browser session and retry');
        }
        if (waitResult !== 'content') {
            throw new CommandExecutionError(`Ctrip bus page did not render schedule rows (state=${String(waitResult)})`);
        }
        const renderedCardCount = await page.evaluate(buildScrollUntilJs('.list-item-parent', limit));
        const raw = await page.evaluate(buildBusExtractJs());
        if (!Array.isArray(raw)) {
            throw new CommandExecutionError('Ctrip bus DOM extraction returned malformed rows');
        }
        if (raw.length === 0) {
            if (Number(renderedCardCount) > 0) {
                throw new CommandExecutionError('Ctrip bus rows rendered but parser did not find required schedule anchors');
            }
            throw new EmptyResultError('ctrip bus', `No coaches for ${fromCity} to ${toCity} on ${date}`);
        }
        return raw.slice(0, limit).map((r, i) => ({
            rank: i + 1,
            departureTime: r.departureTime,
            fromStation: r.fromStation,
            toStation: r.toStation,
            duration: r.duration,
            price: r.price,
            status: r.status,
            url: searchUrl,
        }));
    },
});

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Try a nearby or earlier date within the booking window
  2. Verify the city pair actually has bus service (try the route on bus.ctrip.com manually)
  3. Check city name normalization — a wrong alias may resolve to an unintended city
  4. Treat EmptyResultError as an expected empty response in your automation, not a failure to retry

Example fix

null
Defensive patterns

Strategy: try-catch

Validate before calling

null

Type guard

null

Try / catch

try {
  rows = await ctripBusList({ from, to, date });
} catch (e) {
  if (e instanceof EmptyResultError) {
    console.info(`No buses found for ${route} on ${date} — treating as empty, not failure`);
    rows = [];
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: `clis ctrip bus --from X --to Y --date D` where Ctrip's list page renders zero .list-item-parent cards for that city pair and date (e.g. distant future dates, holidays with cancelled service, or routes with no bus service).

Common situations: Querying a route served only by train/plane; asking for a date beyond Ctrip's booking window; typos in city names resolving to small towns without bus routes.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/4ea92c07b443b792. Report an issue: GitHub.