jackwener/OpenCLI · warning · EmptyResultError

No tour packages for "${destination}"

Error message

No tour packages for "${destination}"

What it means

An EmptyResultError raised by `ctrip tour` when the vacations.ctrip.com tour search page explicitly reports an empty result state (WAIT_FOR_VACATIONS_JS returned 'empty'), meaning no tour packages match the destination keyword. Unlike the render-failure errors, this means the page loaded fine and genuinely has no matching tour lines.

Source

Thrown at clis/ctrip/tour.js:50

    columns: [
        'rank',
        'title', 'subtitle',
        'tags', 'score', 'sold', 'reviews',
        'price',
        'url',
    ],
    func: async (page, kwargs) => {
        const destination = parsePlaceName('destination', kwargs.destination);
        const limit = parseListLimit(kwargs.limit);

        const searchUrl = buildTourListUrl(destination);
        await page.goto(searchUrl);
        const waitResult = await page.evaluate(WAIT_FOR_VACATIONS_JS);
        if (waitResult === 'captcha') {
            throw new AuthRequiredError('vacations.ctrip.com', 'Ctrip is asking for a captcha; complete it in your browser session and retry');
        }
        if (waitResult === 'empty') {
            throw new EmptyResultError('ctrip tour', `No tour packages for "${destination}"`);
        }
        if (waitResult !== 'content') {
            throw new CommandExecutionError(`Ctrip tour page did not render package cards (state=${String(waitResult)})`);
        }
        const raw = await page.evaluate(buildVacationsExtractJs());
        if (!Array.isArray(raw)) {
            throw new CommandExecutionError('Ctrip tour DOM extraction returned malformed rows');
        }
        if (raw.length === 0) {
            throw new CommandExecutionError('Ctrip tour cards rendered but parser did not find required package anchors');
        }
        return raw.slice(0, limit).map((r, i) => ({
            rank: i + 1,
            title: r.title,
            subtitle: r.subtitle,
            tags: r.tags,
            score: r.score,
            sold: r.sold,

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Retry with a major tourist destination keyword such as 北京, 三亚, or 马尔代夫
  2. Use the destination's official Chinese name
  3. If you expected tours, try the `ctrip package` command (flight+hotel tab) instead
  4. Catch EmptyResultError and try alternative keywords in your script

Example fix

// before
const tours = await runCli('ctrip', 'tour', destination);
// after
let tours;
try {
  tours = await runCli('ctrip', 'tour', destination);
} catch (e) {
  if (e.name === 'EmptyResultError') tours = await runCli('ctrip', 'package', destination);
  else throw e;
}
Defensive patterns

Strategy: fallback

Validate before calling

const q = String(dest || '').trim();
if (q.length < 2) console.warn('short/obscure keywords often yield no tour results');

Try / catch

try {
  const tours = await runCli('ctrip', 'tour', dest);
} catch (e) {
  if (e.name === 'EmptyResultError') {
    tours = await runCli('ctrip', 'package', dest); // try flight+hotel tab
  } else throw e;
}

Prevention

When it happens

Trigger: Running `opencli ctrip tour <destination>` where Ctrip's tour search returns zero .list_product_item cards for that keyword — obscure destinations, misspelled names, or destinations Ctrip does not sell tour packages for.

Common situations: Searching tiny towns or non-tourist locations; romanized/English spellings Ctrip does not index; destinations only served by the package (机+酒) tab but not the tour tab; typo'd Chinese characters.

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/60d64ffc8746a191. Report an issue: GitHub.