jackwener/OpenCLI · error · CommandExecutionError

Ctrip bus rows rendered but parser did not find required sch

Error message

Ctrip bus rows rendered but parser did not find required schedule anchors

What it means

When the extract script returns an empty array but the scroll step counted rendered card elements (.list-item-parent), rows exist on screen but the parser failed to find its required schedule anchors in them. The CLI throws CommandExecutionError because this is a parser/DOM mismatch, not an absence of data.

Source

Thrown at clis/ctrip/bus.js:70

        const limit = parseListLimit(kwargs.limit);

        const searchUrl = buildBusListUrl(fromCity, toCity, date);
        await page.goto(searchUrl);
        const waitResult = await page.evaluate(WAIT_FOR_BUS_JS);
        if (waitResult === 'captcha') {
            throw new AuthRequiredError('bus.ctrip.com', 'Ctrip is asking for a captcha; complete it in your browser session and retry');
        }
        if (waitResult !== 'content') {
            throw new CommandExecutionError(`Ctrip bus page did not render schedule rows (state=${String(waitResult)})`);
        }
        const renderedCardCount = await page.evaluate(buildScrollUntilJs('.list-item-parent', limit));
        const raw = await page.evaluate(buildBusExtractJs());
        if (!Array.isArray(raw)) {
            throw new CommandExecutionError('Ctrip bus DOM extraction returned malformed rows');
        }
        if (raw.length === 0) {
            if (Number(renderedCardCount) > 0) {
                throw new CommandExecutionError('Ctrip bus rows rendered but parser did not find required schedule anchors');
            }
            throw new EmptyResultError('ctrip bus', `No coaches for ${fromCity} to ${toCity} on ${date}`);
        }
        return raw.slice(0, limit).map((r, i) => ({
            rank: i + 1,
            departureTime: r.departureTime,
            fromStation: r.fromStation,
            toStation: r.toStation,
            duration: r.duration,
            price: r.price,
            status: r.status,
            url: searchUrl,
        }));
    },
});

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Rerun after a longer settle delay so row content fully hydrates before extraction
  2. Update buildBusExtractJs to match the current row anchor selectors
  3. Report/update the CLI if Ctrip changed their markup permanently

Example fix

null
Defensive patterns

Strategy: fallback

Validate before calling

null

Type guard

null

Try / catch

try {
  rows = await ctripBusList({ from, to, date });
} catch (e) {
  if (e instanceof CommandExecutionError && e.message.includes('schedule anchors')) {
    // fallback: retry once after letting the page fully hydrate, then escalate
    await sleep(5000);
    try { rows = await ctripBusList({ from, to, date }); }
    catch { console.error('Parser anchors stale — update buildBusExtractJs selectors'); rows = []; }
  } else { throw e; }
}

Prevention

When it happens

Trigger: `clis ctrip bus` where buildScrollUntilJs('.list-item-parent', limit) reports renderedCardCount > 0 but buildBusExtractJs() returns [] because the required per-row anchor fields are missing or renamed in the DOM.

Common situations: Ctrip changing internal row markup (anchors) while keeping .list-item-parent wrappers; partially loaded rows (images/meta not hydrated); lazy-rendered cards with placeholder content at scroll time.

Related errors


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