jackwener/OpenCLI · error · ArgumentError

--checkin must be before --checkout

Error message

--checkin must be before --checkout (got ${checkin} .. ${checkout})

What it means

This ArgumentError from clis/trip/hotel-search.js is thrown during argument validation when the parsed --checkin date is not strictly before --checkout (parseIsoDate output comparison checkin >= checkout). Trip.com hotel searches require a positive stay length, so the command fails before making any network request. Both dates appear in the message for easy diagnosis.

Solutions

  1. Correct the arguments so checkout is at least one day after checkin.
  2. Add a pre-flight check in calling scripts: if (!(checkin < checkout)) fail early with a clear message.
  3. If same-day stays are intended, use a hotel day-use product or add one night, since this command does not support zero-night stays.
  4. Ensure date inputs are unambiguous ISO strings to avoid normalization collisions.

Example fix

// before
await runTripHotelSearch({ city: 'shanghai', checkin: '2026-09-10', checkout: '2026-09-10' });
// after
const checkin = '2026-09-10', checkout = '2026-09-11';
if (!(new Date(checkin) < new Date(checkout))) throw new Error('checkin must precede checkout');
await runTripHotelSearch({ city: 'shanghai', checkin, checkout });
Defensive patterns

Strategy: validation

Validate before calling

const ci = new Date(checkin), co = new Date(checkout);
if (isNaN(ci) || isNaN(co)) throw new Error('checkin/checkout must be ISO dates');
if (ci >= co) throw new Error(`--checkin must be before --checkout (got ${checkin} .. ${checkout})`);

Type guard

null

Try / catch

try {
  await runTripHotelSearch(args);
} catch (e) {
  if (e instanceof ArgumentError && /checkin/.test(e.message)) {
    console.error(`Fix date range: ${e.message}`);
    process.exitCode = 2;
  } else throw e;
}

Prevention

When it happens

Trigger: Invoking hotel-search with --checkin and --checkout that are equal or inverted, e.g. --checkin 2026-09-10 --checkout 2026-09-10 or --checkin 2026-09-15 --checkout 2026-09-10.

Common situations: Same-day 'day use' bookings mistakenly given identical dates; swapped arguments in a script or shell alias; timezone/time parsing making two intended-different dates normalize to the same ISO date; copy-paste errors leaving checkout as an older date.

Related errors


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

Appendix: source

Thrown at clis/trip/hotel-search.js:47

    args: [
        { name: 'city', required: true, positional: true, help: 'Numeric Trip.com city id (discover via the hotels search box; e.g. 338 for London)' },
        { name: 'checkin', required: true, help: 'Check-in date (YYYY-MM-DD)' },
        { name: 'checkout', required: true, help: 'Check-out date (YYYY-MM-DD)' },
        { name: 'limit', type: 'int', default: 20, help: 'Number of hotels (1-50)' },
    ],
    columns: [
        'rank',
        'name', 'score', 'reviewLabel', 'reviews',
        'location', 'room',
        'price', 'currency',
        'url',
    ],
    func: async (page, kwargs) => {
        const cityId = parseCityId('city', kwargs.city);
        const checkin = parseIsoDate('checkin', kwargs.checkin);
        const checkout = parseIsoDate('checkout', kwargs.checkout);
        if (checkin >= checkout) {
            throw new ArgumentError(`--checkin must be before --checkout (got ${checkin} .. ${checkout})`);
        }
        const limit = parseListLimit(kwargs.limit);

        const searchUrl = buildHotelSearchUrl(cityId, checkin, checkout);
        await page.goto(searchUrl);
        const waitResult = await page.evaluate(WAIT_FOR_HOTELS_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 !== 'content') {
            throw new CommandExecutionError(`Trip.com hotel page did not render hotel cards (state=${String(waitResult)})`);
        }
        const raw = await page.evaluate(buildHotelExtractJs());
        if (!Array.isArray(raw)) {
            throw new CommandExecutionError('Trip.com hotel DOM extraction returned malformed rows');
        }
        if (raw.length === 0) {
            throw new EmptyResultError('trip hotel-search', `No hotels for city ${cityId} on ${checkin} .. ${checkout}`);

View on GitHub (pinned to 49907e53dc)