jackwener/OpenCLI · error · ArgumentError

--${name} is required (3-letter IATA code, e.g. PEK, SHA)

Error message

--${name} is required (3-letter IATA code, e.g. PEK, SHA)

What it means

parseIataCode throws this ArgumentError when the airport/metro code option is missing (undefined, null, or empty string). Flight commands require both --from and --to codes, and the library refuses to guess. Valid codes are 3-letter IATA airport codes (PEK, PVG) or metro-group codes (BJS, SHA).

Source

Thrown at clis/ctrip/utils.js:237

    const day = Number(m[3]);
    if (month < 1 || month > 12 || day < 1 || day > 31) {
        throw new ArgumentError(`--${name} has invalid month/day: ${value}`);
    }
    // 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 {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Provide the flag with a 3-letter code, e.g. --from PEK --to SHA
  2. Look up codes with `ctrip search` (city suggestions include ids) or an IATA lookup
  3. Fix the empty env/shell variable feeding the flag
  4. Use metro codes (BJS for Beijing, SHA for Shanghai) when unsure of the specific airport

Example fix

// before
ctrip flight --to SHA
// after
ctrip flight --from PEK --to SHA --date 2026-09-01
Defensive patterns

Strategy: validation

Validate before calling

function requireIata(value, name) {
  const v = String(value ?? '').trim().toUpperCase();
  if (!/^[A-Z]{3}$/.test(v)) throw new Error(`--${name} must be a 3-letter IATA code`);
  return v;
}

Type guard

function isIataCode(v) {
  return typeof v === 'string' && /^[A-Za-z]{3}$/.test(v.trim());
}

Try / catch

try {
  const from = parseIataCode('from', rawFrom);
} catch (err) {
  if (err instanceof ArgumentError && /is required/.test(err.message)) {
    // prompt the user or fall back to a default origin
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling parseIataCode(name, raw) from --fromCode/--toCode paths when the flag was omitted or passed empty, e.g. `ctrip flight --to SHA` without --from.

Common situations: User doesn't know the code and omits the flag; empty env var feeds the flag; script builds args conditionally and drops one; user passes a city name ('Beijing') instead of a code.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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