jackwener/OpenCLI · warning · EmptyResultError

No timetable for ${from} to ${to} (${country})

Error message

No timetable for ${from} to ${to} (${country})

What it means

EmptyResultError thrown when the Trip.com train page rendered correctly and extraction succeeded, but zero train rows were found for the requested from/to/country combination. This is a clean 'no data' signal, not a failure of the scraper.

Source

Thrown at clis/trip/train.js:63

        const to = parseKeyword('to', kwargs.to);
        const country = parseKeyword('country', kwargs.country);
        const limit = parseListLimit(kwargs.limit);

        const searchUrl = buildTrainRouteUrl(country, from, to);
        await page.goto(searchUrl);
        const waitResult = await page.evaluate(WAIT_FOR_TRAINS_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 !== 'content') {
            throw new CommandExecutionError(`Trip.com train timetable did not render (state=${String(waitResult)}); check the city names and --country`);
        }
        const raw = await page.evaluate(buildTrainExtractJs());
        if (!Array.isArray(raw)) {
            throw new CommandExecutionError('Trip.com train DOM extraction returned malformed rows');
        }
        if (raw.length === 0) {
            throw new EmptyResultError('trip train', `No timetable for ${from} to ${to} (${country})`);
        }
        return raw.slice(0, limit).map((r, i) => ({
            rank: i + 1,
            departureTime: r.departureTime,
            fromStation: r.fromStation,
            arrivalTime: r.arrivalTime,
            toStation: r.toStation,
            duration: r.duration,
            changes: r.changes,
            url: searchUrl,
        }));
    },
});

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Verify the route actually has train service on trip.com in a browser
  2. Check the date is within Trip.com's bookable timetable window
  3. Try nearby major stations or adjust --country
  4. Handle EmptyResultError gracefully in the caller instead of retrying

Example fix

// before
try { rows = await getTripTrains({ from, to, country }); }
catch (e) { retry(e); }
// after
try { rows = await getTripTrains({ from, to, country }); }
catch (e) {
  if (e instanceof EmptyResultError) return [];
  throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// sanity-check the route before calling
const railPairs = new Set(['london|paris','paris|rome']);
if (!railPairs.has(`${from.toLowerCase()}|${to.toLowerCase()}`)) {
  console.warn(`route ${from}->${to} may have no train service`);
}

Type guard

null

Try / catch

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

Prevention

When it happens

Trigger: Querying a route with no direct train service (e.g. London to New York), a date far in the future or in the past with no timetable, or a city pair Trip.com does not index for trains in the given --country.

Common situations: Users asking for train times between cities connected only by air; querying yesterday's date; picking regional stations that Trip.com treats as separate cities; non-rail city pairs in markets like the US where Trip.com trains coverage is thin.

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