jackwener/OpenCLI · error · ArgumentError
checkout (${checkout}) must be after checkin (${checkin})
Error message
checkout (${checkout}) must be after checkin (${checkin}) What it means
This ArgumentError is thrown by the booking search command when the checkout date is not strictly after the checkin date. The library normalizes both dates to a comparable form and performs a simple string/lexicographic comparison (checkin >= checkout), so equal or inverted ranges are rejected before any browser automation starts. It exists to prevent building a Booking.com URL with an invalid date range that would yield no results or an error page.
Source
Thrown at clis/booking/search.js:245
'name',
'country',
'slug',
'star_rating',
'review_score',
'review_count',
'price_amount',
'price_currency',
'distance',
'recommended_room',
'url',
],
func: async (page, kwargs) => {
const destination = String(kwargs.destination || '').trim();
if (!destination) throw new ArgumentError('destination is required');
const checkin = normalizeDate(kwargs.checkin, 'checkin');
const checkout = normalizeDate(kwargs.checkout, 'checkout');
if (checkin >= checkout) {
throw new ArgumentError(`checkout (${checkout}) must be after checkin (${checkin})`);
}
const adults = normalizePositiveInt(kwargs.adults, 2, 'adults', 30);
const rooms = normalizePositiveInt(kwargs.rooms, 1, 'rooms', 30);
const children = normalizeNonNegativeInt(kwargs.children, 0, 'children', 10);
const currency = normalizeCurrency(kwargs.currency);
const lang = normalizeLang(kwargs.lang);
const limit = normalizePositiveInt(kwargs.limit, 25, 'limit', 100);
const offset = normalizeNonNegativeInt(kwargs.offset, 0, 'offset', 1000);
const url = buildSearchUrl({ destination, checkin, checkout, adults, rooms, children, offset, currency, lang });
try {
await page.goto(url);
} catch (err) {
throw new CommandExecutionError(`Failed to load Booking.com search page: ${err?.message || err}`);
}
// Booking lazy-loads price cells; wait for at least the first card price to settle.View on GitHub (pinned to 49907e53dc)
Solutions
- Pass a checkout date strictly after checkin (at least one night apart).
- Swap the values if they were accidentally reversed.
- Verify date format expected by normalizeDate (ISO yyyy-mm-dd) and convert before calling.
- If a same-day booking is intended, this API does not support it; check for a dedicated option or use a different tool.
Example fix
// before
await run('booking.search', { destination: 'Paris', checkin: '2026-05-10', checkout: '2026-05-10' });
// after
await run('booking.search', { destination: 'Paris', checkin: '2026-05-10', checkout: '2026-05-11' }); Defensive patterns
Strategy: validation
Validate before calling
function assertValidStay(checkin, checkout) {
const ckin = new Date(checkin), ckout = new Date(checkout);
if (isNaN(ckin) || isNaN(ckout)) throw new Error('dates must be valid');
if (ckout <= ckin) throw new Error(`checkout (${checkout}) must be after checkin (${checkin})`);
}
// call before the API:
assertValidStay('2026-05-10', '2026-05-11'); Type guard
const isAfter = (checkin, checkout) => String(checkout) > String(checkin); // ISO dates compare lexicographically
Try / catch
try {
await booking.search({ destination, checkin, checkout });
} catch (e) {
if (e instanceof ArgumentError && /must be after checkin/.test(e.message)) {
[checkin, checkout] = [checkin, addDays(checkin, 1)]; // or surface to user
} else throw e;
} Prevention
- Always compute checkout as checkin + N nights in one place in your code.
- Use ISO yyyy-mm-dd strings for both dates to avoid format ambiguity.
- Add a unit test asserting checkout > checkin before invoking the CLI.
- Never allow the same value for checkin and checkout in your UI/CLI wrapper.
When it happens
Trigger: Calling the search command with checkin equal to checkout (e.g. checkin=2026-01-10, checkout=2026-01-10), or with checkout earlier than checkin (e.g. dates swapped or checkout omitted and defaulted to a date before checkin).
Common situations: Users passing a single-night stay as the same date for both fields; computing dates with an off-by-one or swapped variable; passing MM/DD vs DD/MM formats so normalizeDate parses them differently than expected; passing checkout as a relative date like 'tomorrow' when checkin was 'today+2'.
Related errors
- archive search sort must be one of ${SORT_OPTIONS.join(', ')
- archive search mediatype must be one of ${MEDIATYPES.join(',
- archive search limit must be a positive integer
- archive search limit must be <= 100
- archive search query must not be empty
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/03e5ffadd5dd4a17.
Report an issue: GitHub.