jackwener/OpenCLI · info · EmptyResultError

No attractions for "${query}"

Error message

No attractions for "${query}"

What it means

The `trip attraction` command treats a successful page load with zero product cards as a legitimate empty result and throws EmptyResultError scoped to 'trip attraction'. Trip.com rendered fine and no verification was required — the destination keyword simply matched no things-to-do products. It is thrown when WAIT_FOR_ATTRACTIONS_JS resolves to 'empty'.

Source

Thrown at clis/trip/attraction.js:51

    columns: [
        'rank',
        'name',
        'rating', 'reviews', 'booked',
        'price', 'currency',
        'url',
    ],
    func: async (page, kwargs) => {
        const query = parseKeyword('query', kwargs.query);
        const limit = parseListLimit(kwargs.limit);

        const searchUrl = buildAttractionSearchUrl(query);
        await page.goto(searchUrl);
        const waitResult = await page.evaluate(WAIT_FOR_ATTRACTIONS_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 attraction', `No attractions for "${query}"`);
        }
        if (waitResult !== 'content') {
            throw new CommandExecutionError(`Trip.com things-to-do page did not render product cards (state=${String(waitResult)})`);
        }
        const raw = await page.evaluate(buildAttractionExtractJs());
        if (!Array.isArray(raw)) {
            throw new CommandExecutionError('Trip.com attraction DOM extraction returned malformed rows');
        }
        if (raw.length === 0) {
            throw new CommandExecutionError('Trip.com attraction cards rendered but parser did not find required detail-link anchors');
        }
        return raw.slice(0, limit).map((r, i) => ({
            rank: i + 1,
            name: r.name,
            rating: r.rating,
            reviews: r.reviews,
            booked: r.booked,
            price: r.price,

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Verify and simplify the keyword (e.g. 'Tokyo' instead of a neighborhood or misspelling) and retry.
  2. Try the destination in English, as Trip.com's international things-to-do search matches English names best.
  3. Broaden the query to the nearest major city or region that has attractions listed.
  4. If you expect results for a known destination, complete a Trip.com verification first (region inventory can be gated) and retry.

Example fix

// before
await runCli(['trip', 'attraction', 'Tokio']);
// after: catch EmptyResultError and retry with corrected keyword
try {
  await runCli(['trip', 'attraction', rawQuery]);
} catch (e) {
  if (e.name === 'EmptyResultError') return runCli(['trip', 'attraction', correctedKeyword]);
  throw e;
}
Defensive patterns

Strategy: fallback

Validate before calling

null

Type guard

null

Try / catch

try {
  return await runCli(['trip', 'attraction', query]);
} catch (e) {
  if (e.name === 'EmptyResultError') {
    return []; // no attractions for this keyword
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling `trip attraction <query>` when the things-to-do search page for that keyword renders but contains no attraction product cards (waitResult === 'empty'), e.g. misspelled or non-tourist destination keywords.

Common situations: Typo'd or overly specific keywords ('Tokio', 'Louvre museum tickets price'); searching a tiny town or non-tourist location with no listed attractions; keyword that matches only hotels/flights, not experiences; Trip.com regional site having no inventory for the destination.

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