jackwener/OpenCLI · error · ArgumentError

--${name} must be a 3-letter IATA code, got ${JSON.stringify

Error message

--${name} must be a 3-letter IATA code, got ${JSON.stringify(raw)}

What it means

parseIataCode validates CLI flags (e.g. --from/--to) that must be exactly three uppercase ASCII letters forming an IATA airport/city code. After trimming and uppercasing the raw input, anything not matching /^[A-Z]{3}$/ is rejected. It throws ArgumentError so the CLI fails fast with a clear message instead of sending a malformed code to Ctrip's sites.

Source

Thrown at clis/ctrip/utils.js:241

    // Cross-check via UTC date math so 2026-02-30 doesn't pass.
    const parsed = new Date(Date.UTC(year, month - 1, day));
    if (parsed.getUTCFullYear() !== year || parsed.getUTCMonth() !== month - 1 || parsed.getUTCDate() !== day) {
        throw new ArgumentError(`--${name} is not a real calendar date: ${value}`);
    }
    return value;
}

/**
 * Validate a 3-letter IATA airport / metro code, return uppercase.
 * Ctrip URL accepts both single-airport (PEK / PVG) and metro-group (BJS / SHA) codes.
 */
export function parseIataCode(name, raw) {
    if (raw === undefined || raw === null || raw === '') {
        throw new ArgumentError(`--${name} is required (3-letter IATA code, e.g. PEK, SHA)`);
    }
    const value = String(raw).trim().toUpperCase();
    if (!/^[A-Z]{3}$/.test(value)) {
        throw new ArgumentError(`--${name} must be a 3-letter IATA code, got ${JSON.stringify(raw)}`);
    }
    return value;
}

/**
 * Validate a numeric Ctrip city ID (returned by `ctrip search` / `ctrip hotel-suggest`).
 */
export function parseCityId(raw) {
    if (raw === undefined || raw === null || raw === '' || String(raw).trim() === '') {
        throw new ArgumentError('--city is required (numeric city ID from `ctrip search` or `ctrip hotel-suggest`)');
    }
    try {
        return parseStrictPositiveInteger('city', raw);
    } catch {
        throw new ArgumentError(`--city must be a positive integer city ID, got ${JSON.stringify(raw)}`);
    }
}

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Look up the correct 3-letter IATA code (e.g. PEK, SHA, CAN) via `ctrip search` and pass it, upper- or lowercase (it is normalized).
  2. Remove surrounding characters/whitespace or digits from the value; only 3 letters are allowed.
  3. If you have an ICAO code (4 letters), convert it to the IATA code before calling.
  4. Ensure the flag is actually provided on the command line and not expanded to an empty shell variable.

Example fix

// before
ctrip flights --from "Beijing" --to sha
// after
ctrip flights --from PEK --to SHA
Defensive patterns

Strategy: validation

Validate before calling

function validIata(v) { return typeof v === 'string' && /^[A-Za-z]{3}$/.test(v.trim()); }
if (!validIata(from) || !validIata(to)) throw new Error('from/to must be 3-letter IATA codes');

Type guard

const isIataCode = (v) => typeof v === 'string' && /^[A-Z]{3}$/.test(v.trim().toUpperCase());

Try / catch

try {
  const code = parseIataCode('from', raw);
} catch (e) {
  if (e instanceof ArgumentError) { console.error('Usage: --from PEK (3-letter IATA code)'); process.exitCode = 2; }
  else throw e;
}

Prevention

When it happens

Trigger: Calling a ctrip command (flight/train list via fromCode/toCode paths) with --from or --to set to undefined, an empty string, a 2- or 4-letter string, a code containing digits or non-Latin characters (e.g. 'PEK1', 'pek ', '北京'), or a full airport name like 'Beijing Capital'.

Common situations: Users pass city names instead of IATA codes, pass lowercase/double-quoted codes with stray whitespace that still contain extra characters, copy a 4-letter ICAO code (ZBAA) instead of the 3-letter IATA code (PEK), or forget the flag entirely on a shell where an empty variable expands to ''. Multi-byte Chinese input also fails since it isn't [A-Z]{3}.

Understand the failure class

Background: "Unknown argument", "Invalid value", and "must be one of": invalid CLI argument errors explained — this error's family across 35 libraries.

Related errors


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