jackwener/OpenCLI · info · EmptyResultError

No ${kwargs.type || 'private'} tours for "${query}"

Error message

No ${kwargs.type || 'private'} tours for "${query}"

What it means

This EmptyResultError means the tour search page explicitly reported 'no routes found' for the query (result.status === 'empty'), i.e. Trip.com has no matching tours for that destination and tour type. It is a clean no-match signal, deliberately separated from schema-drift and captcha cases.

Source

Thrown at clis/trip/tour.js:62

        'price', 'currency',
        'url',
    ],
    func: async (page, kwargs) => {
        const query = parseKeyword('query', kwargs.query);
        const tourType = parseTourType(kwargs.type);
        const limit = parseListLimit(kwargs.limit);

        const searchUrl = buildTourSearchUrl(query, tourType);
        await page.goto(searchUrl);
        const result = await page.evaluate(buildTourSearchJs(query));
        if (!result || typeof result !== 'object') {
            throw new CommandExecutionError('Trip.com tour search returned malformed data');
        }
        if (result.status === 'captcha') {
            throw new AuthRequiredError('trip.com', 'Trip.com is asking for a verification; complete it in your browser session and retry');
        }
        if (result.status === 'empty') {
            throw new EmptyResultError('trip tour', `No ${kwargs.type || 'private'} tours for "${query}"`);
        }
        if (result.status !== 'content') {
            throw new CommandExecutionError(`Trip.com tour search did not return results (state=${String(result.status)})`);
        }
        // Products captured but none carry a name is drift (schema moved), not an empty search;
        // a genuine no-match resolves as status 'empty' above off the page's "0 routes found".
        const rows = Array.isArray(result.rows) ? result.rows.filter((r) => r.name) : [];
        if (rows.length === 0) {
            throw new CommandExecutionError('Trip.com tour search captured products but none carried a name (the product markup may have changed)');
        }
        return rows.slice(0, limit).map((r, i) => ({
            rank: i + 1,
            name: r.name,
            type: r.type,
            rating: r.rating,
            reviews: r.reviews,
            price: r.price,
            currency: 'USD',

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Try the other --type value (group vs private) — availability differs per tab.
  2. Simplify or correct the destination query string.
  3. Search a nearby major city that has tour inventory.
  4. Catch EmptyResultError and treat it as an empty result set in your application.

Example fix

// before
await tripTour({ query: 'Hallstatt', type: 'group' }); // no group tours
// after
try {
  return await tripTour({ query: 'Hallstatt', type: 'private' });
} catch (e) {
  if (e.name === 'EmptyResultError') return [];
  throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// sanity-check the query before spending a page load
if (!query || query.trim().length < 3) throw new Error('provide a meaningful destination name');

Type guard

function isPlausibleDestination(q) { return typeof q === 'string' && q.trim().length >= 3; }

Try / catch

try {
  const rows = await tourSearch(query, type);
} catch (e) {
  if (e instanceof EmptyResultError) return [];
  throw e;
}

Prevention

When it happens

Trigger: Calling tour search with a destination that has zero private (or group, per --type) tours on Trip.com, or a misspelled/obscure query that matches no tour products.

Common situations: Small towns or attractions Trip.com doesn't sell tours for; using --type=group in a market where only private tours exist; localized transliterations that match nothing.

Related errors


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