jackwener/OpenCLI · error · CommandExecutionError

Trip.com things-to-do page did not render product cards (sta

Error message

Trip.com things-to-do page did not render product cards (state=${String(waitResult)})

What it means

The `trip attraction` command throws this CommandExecutionError when the in-page wait script neither confirmed content ('content'), emptiness ('empty'), nor a challenge ('captcha') — the page ended in some other state, so product cards never rendered. The state value is embedded in the message for debugging. It usually means Trip.com's SPA never finished hydrating or changed its loading markup.

Source

Thrown at clis/trip/attraction.js:54

        '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,
            currency: 'USD',
            url: r.url,
        }));

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Read the `state=` value in the message: if it indicates a timeout, simply retry — slow renders are often transient.
  2. Increase browser navigation/wait timeouts in the shared page setup and rerun.
  3. Check Trip.com in a normal browser to see whether the things-to-do page layout changed; if so the library's wait script needs updating.
  4. Improve network conditions or run closer to Trip.com's region to speed up client-side hydration.

Example fix

// before
await runCli(['trip', 'attraction', query]);
// after: retry once on render-state failure
try {
  await runCli(['trip', 'attraction', query]);
} catch (e) {
  if (e.name === 'CommandExecutionError' && /did not render product cards/.test(e.message)) {
    await sleep(3000);
    return runCli(['trip', 'attraction', query]);
  }
  throw e;
}
Defensive patterns

Strategy: retry

Validate before calling

null

Type guard

null

Try / catch

async function withRetry(fn, attempts = 2) {
  for (let i = 0; i < attempts; i++) {
    try {
      return await fn();
    } catch (e) {
      const transient = /did not render product cards \(state=/.test(e.message);
      if (transient && i < attempts - 1) { await sleep(3000); continue; }
      throw e;
    }
  }
}

Prevention

When it happens

Trigger: page.evaluate(WAIT_FOR_ATTRACTIONS_JS) returns any value other than 'content'/'empty'/'captcha' — e.g. a timeout sentinel or null — after page.goto on the attraction search URL, such as slow client-side rendering exceeding the wait script's internal deadline.

Common situations: Slow network / throttled connection where hydration outlasts the wait window; Trip.com A/B tests changing the things-to-do page structure so the wait selector never matches; transient server errors returning a stub page; heavy CPU contention on the machine running the headless browser.

Related errors


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