jackwener/OpenCLI · error · CommandExecutionError

Trip.com package search returned malformed payload: missing

Error message

Trip.com package search returned malformed payload: missing grouplist array

What it means

The Trip.com package-search adapter parsed the HTTP response successfully as JSON, but the resulting object did not contain a `grouplist` array, which is the field the adapter relies on for package flight groups. This is thrown as a CommandExecutionError because the underlying command (an upstream Trip.com API/scrape call) executed but produced an unexpected shape. It signals an upstream contract change, an anti-bot/error page rendered as JSON, or a non-200 body that still parses as JSON.

Source

Thrown at clis/trip/utils.js:967

        response = await fetch(PACKAGE_SEARCH_ENDPOINT, {
            method: 'POST',
            headers: { 'content-type': 'application/json', currency: 'USD' },
            body: JSON.stringify(body),
        });
    } catch (err) {
        throw new CommandExecutionError(`Trip.com package search fetch failed: ${err instanceof Error ? err.message : String(err)}`);
    }
    if (!response.ok) {
        throw new CommandExecutionError(`Trip.com package search failed with status ${response.status}`);
    }
    let payload;
    try {
        payload = await response.json();
    } catch (err) {
        throw new CommandExecutionError(`Trip.com package search returned invalid JSON: ${err instanceof Error ? err.message : String(err)}`);
    }
    if (!Array.isArray(payload?.grouplist)) {
        throw new CommandExecutionError('Trip.com package search returned malformed payload: missing grouplist array');
    }
    return payload.grouplist;
}

/**
 * Project a package flight group into the stable adapter column shape. A group's
 * `flightlist` is the itinerary legs (one for a nonstop), so the route summary
 * reads the departure off the first leg and the arrival off the last, with the
 * leg count minus one as the stop count. `price` is the per-person package
 * starting fare (`policylist[0].price.price`); missing values stay `null`.
 */
export function mapPackageRow(group, index) {
    const legs = Array.isArray(group?.flightlist) ? group.flightlist : [];
    const first = legs[0] || {};
    const last = legs[legs.length - 1] || {};
    const binfo = first.binfo || {};
    const price = group?.policylist?.[0]?.price?.price;
    const str = (v) => (v == null || v === '') ? null : String(v).replace(/\s+/g, ' ').trim();

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-run the search with different dates/route to rule out an empty upstream result before assuming a schema change.
  2. Log the raw payload (before the grouplist check) to see what Trip.com actually returned (error envelope, CAPTCHA, or schema change).
  3. Check for an updated version of the opencli trip adapter that matches the current Trip.com response schema.
  4. If Trip.com changed the schema, update fetchPackageSearch to read the new field name and re-validate with Array.isArray.
  5. Retry later or from a different network if anti-bot responses are suspected.

Example fix

// before
if (!Array.isArray(payload?.grouplist)) {
    throw new CommandExecutionError('Trip.com package search returned malformed payload: missing grouplist array');
}
return payload.grouplist;
// after
const groups = payload?.grouplist ?? payload?.data?.grouplist;
if (!Array.isArray(groups)) {
    throw new CommandExecutionError(`Trip.com package search returned malformed payload: missing grouplist array (keys: ${Object.keys(payload ?? {}).join(',')})`);
}
return groups;
Defensive patterns

Strategy: validation

Validate before calling

const payload = await response.json().catch(() => null);
if (!payload || typeof payload !== 'object' || !Array.isArray(payload.grouplist)) {
    throw new Error('Trip.com package search payload missing grouplist array');
}

Type guard

function hasGrouplist(p) {
    return typeof p === 'object' && p !== null && Array.isArray(p.grouplist);
}

Try / catch

try {
    const groups = await fetchPackageSearch(params);
} catch (err) {
    if (err instanceof CommandExecutionError && err.message.includes('malformed payload')) {
        // log raw payload for diagnosis, surface a friendly 'Trip.com returned no package data' message
    } else {
        throw err;
    }
}

Prevention

When it happens

Trigger: Calling fetchPackageSearch (via the `groups` command) when Trip.com returns JSON without `grouplist` — e.g. the API changed its response schema, returned a CAPTCHA/error JSON envelope, or an empty/error payload for the searched route/date.

Common situations: Trip.com silently changing their package-search response schema; rate-limiting or bot detection returning a JSON error object; querying obscure routes/dates where the upstream returns no group data but a valid JSON object; stale adapter code after a Trip.com site update.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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