jackwener/OpenCLI · error · CommandExecutionError

Ctrip flight network capture returned malformed entries

Error message

Ctrip flight network capture returned malformed entries

What it means

A CommandExecutionError thrown by parseBatchSearchCaptures in clis/ctrip/flight.js when the entries passed in from the network-capture phase are not an array. The flight CLI listens for Ctrip's batch-search XHR responses (entries matching CAPTURE_PATTERN) and this guard rejects a malformed capture payload before any parsing proceeds.

Source

Thrown at clis/ctrip/flight.js:59

function cleanString(value) {
    return typeof value === 'string' ? value.trim() : '';
}

function timePart(value) {
    const match = cleanString(value).match(/(?:^|\s)([0-2]\d:[0-5]\d)(?::[0-5]\d)?$/);
    return match?.[1] || '';
}

function cabinLabel(value) {
    const labels = { Y: '经济舱', S: '超级经济舱', C: '公务舱', F: '头等舱' };
    const codes = [...new Set(cleanString(value).toUpperCase().match(/[YSCF]/g) || [])];
    return codes.length > 0 ? codes.map((code) => labels[code]).join('/') : (cleanString(value) || null);
}

function parseBatchSearchCaptures(entries) {
    if (!Array.isArray(entries)) {
        throw new CommandExecutionError('Ctrip flight network capture returned malformed entries');
    }
    const captured = entries.filter((entry) => String(entry?.url || '').includes(CAPTURE_PATTERN));
    if (captured.length === 0) return null;

    const byId = new Map();
    let finished = false;
    for (const entry of captured) {
        const status = Number(entry?.responseStatus || 0);
        if (status === 401 || status === 403) {
            throw new AuthRequiredError('flights.ctrip.com', `Ctrip flight API returned HTTP ${status}; complete any verification in the browser and retry`);
        }
        if (status !== 200) {
            throw new CommandExecutionError(`Ctrip flight API returned HTTP ${status || 'unknown'}`);
        }
        if (entry?.responseBodyTruncated === true) {
            throw new CommandExecutionError('Ctrip flight API response exceeded the browser capture limit');
        }
        if (typeof entry?.responsePreview !== 'string') {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Retry the command — a transient capture failure often disappears on rerun.
  2. Update the library in case a capture-shape fix has shipped.
  3. Check the browser session is healthy (page loaded, no crash) and rerun in a fresh session.
  4. If reproducible, file an issue with the command and version — this indicates the capture layer, not your input, is broken.

Example fix

// before
const result = await cli(['flight', '--from','PEK','--to','SHA','--date',d]);
// after
try { const result = await cli(['flight', ...]); } catch (e) {
  if (String(e.message).includes('malformed entries')) return await cli(['flight', ...]); // retry once
  throw e;
}
Defensive patterns

Strategy: retry

Type guard

function isMalformedCaptureError(e) { return e && String(e.message || '').includes('malformed entries'); }

Try / catch

try { return await runFlightItineraries(args); }
catch (e) { if (isMalformedCaptureError(e)) { await sleep(5000); return await runFlightItineraries(args); } throw e; }

Prevention

When it happens

Trigger: itineraries calls parseBatchSearchCaptures with a non-array value (null/undefined/object) instead of the expected array of captured network entries — e.g. the browser capture step failed, returned nothing, or the plumbing passed the wrong shape.

Common situations: Browser extension/CDP capture layer silently failing so no entries were collected; internal wiring bug between capture and parse; library version drift where the capture API changed shape; page crashed before any batch-search request fired.

Understand the failure class

Related errors


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