jackwener/OpenCLI · warning · EmptyResultError

No airport transfers for ${city} (${airport})

Error message

No airport transfers for ${city} (${airport})

What it means

EmptyResultError thrown when the transfer page probe returns 'empty': Trip.com rendered the airport-transfer flow but found no transfer options for the given city/airport pair. The scraper worked; the data does not exist.

Source

Thrown at clis/trip/transfer.js:56

        'rank',
        'type',
        'passengers', 'luggage',
        'price', 'currency',
        'url',
    ],
    func: async (page, kwargs) => {
        const city = parseKeyword('city', kwargs.city);
        const airport = parseIataCode('airport', kwargs.airport);
        const limit = parseListLimit(kwargs.limit);

        const listUrl = buildTransferListUrl(city, airport);
        await page.goto(listUrl);
        const waitResult = await page.evaluate(WAIT_FOR_TRANSFERS_JS);
        if (waitResult === 'captcha') {
            throw new AuthRequiredError('trip.com', 'Trip.com is asking for a verification; complete it in your browser session and retry');
        }
        if (waitResult === 'empty') {
            throw new EmptyResultError('trip transfer', `No airport transfers for ${city} (${airport})`);
        }
        if (waitResult !== 'content') {
            throw new CommandExecutionError(`Trip.com transfer listing did not render (state=${String(waitResult)}); check the city and airport code`);
        }
        const landedPath = await page.evaluate('location.pathname');
        if (!/\/airport-transfers\/[^/]+\/airport-[^/]+/i.test(String(landedPath))) {
            throw new CommandExecutionError(`Trip.com bounced ${city} / ${airport} to the transfer landing; check the city name matches the airport IATA code`);
        }
        const raw = await page.evaluate(buildTransferExtractJs());
        if (!Array.isArray(raw)) {
            throw new CommandExecutionError('Trip.com transfer DOM extraction returned malformed rows');
        }
        if (raw.length === 0) {
            throw new CommandExecutionError('Trip.com transfer cards rendered but parser did not find required price anchors');
        }
        return raw.slice(0, limit).map((r, i) => ({
            rank: i + 1,
            type: r.type,

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Verify the airport has transfer listings on trip.com in a browser
  2. Double-check the IATA code is the intended airport
  3. Try the nearest major airport instead
  4. Treat EmptyResultError as a legitimate empty answer in your tool, not a bug

Example fix

// before
const rows = await getTransfers('XQT'); // bogus code
// after
const rows = await getTransfers('LHR');
Defensive patterns

Strategy: try-catch

Validate before calling

// only query major airports known to have transfer inventory
const noTransfers = new Set(['XQT',' tiny regional codes']);
if (noTransfers.has(airport)) return [];

Type guard

null

Try / catch

try {
  const rows = await getTransfers(args);
} catch (e) {
  if (e instanceof EmptyResultError) return [];
  throw e;
}

Prevention

When it happens

Trigger: Querying an airport code that has no transfer listings on Trip.com (small regional airports), or a city/IATA mismatch where Trip.com resolves to a location with no transfer inventory.

Common situations: Small or secondary airports (e.g. some regional fields) with no bookable transfers; typo'd IATA codes resolving to unexpected cities; markets where Trip.com doesn't sell transfers.

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