jackwener/OpenCLI · info · EmptyResultError

ctrip package

Error message

ctrip package

What it means

EmptyResultError thrown when the vacations wait script reports state 'empty' — the page rendered successfully but contains no flight-plus-hotel package cards for the requested destination. This is a legitimate no-results signal, distinct from a captcha or render failure, surfaced as EmptyResultError with the destination echoed.

Source

Thrown at clis/ctrip/package.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 = buildPackageListUrl(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 package', `No flight-plus-hotel packages for "${destination}"`);
        }
        if (waitResult !== 'content') {
            throw new CommandExecutionError(`Ctrip package page did not render package cards (state=${String(waitResult)})`);
        }
        const raw = await page.evaluate(buildVacationsExtractJs());
        if (!Array.isArray(raw)) {
            throw new CommandExecutionError('Ctrip package DOM extraction returned malformed rows');
        }
        if (raw.length === 0) {
            throw new CommandExecutionError('Ctrip package 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 destination city name (e.g. 三亚, 厦门) or fix spelling
  2. Adjust travel dates — packages may be unavailable for the chosen period
  3. Confirm the destination on vacations.ctrip.com manually to verify zero inventory
  4. Try from a locale/IP where the inventory is offered

Example fix

// before
await ctrip.package({ destination: 'Sanya ' }); // trailing space/English name may yield empty
// after
await ctrip.package({ destination: '三亚' });
Defensive patterns

Strategy: fallback

Validate before calling

const dest = String(kwargs.destination ?? '').trim();
if (!dest) throw new Error('destination is required');
// prefer major-city names that are known to carry package inventory
const KNOWN_PACKAGE_CITIES = ['三亚', '厦门', '丽江', '桂林'];

Type guard

const isKnownPackageDestination = (d) => typeof d === 'string' && d.trim().length > 0;

Try / catch

try {
  return await ctrip.package({ destination });
} catch (e) {
  if (e instanceof EmptyResultError) {
    return []; // genuine no-results: offer alternate destinations in UI
  }
  throw e;
}

Prevention

When it happens

Trigger: WAIT_FOR_VACATIONS_JS returns 'empty' after loading buildPackageListUrl(destination): the destination has no package inventory (obscure or international destinations, off-season dates), or the destination string is misspelled so Ctrip returns a zero-card results page.

Common situations: Searching niche destinations without package products; typo'd destination strings; date ranges where packages are sold out; region-locked inventory not offered to the current IP/locale.

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