jackwener/OpenCLI · error · ArgumentError

--from station must not be empty

Error message

--from station must not be empty

What it means

The `12306 price` command requires both origin and destination. This ArgumentError is thrown when the `--from` option is missing or empty after trimming, before any network request is made.

Source

Thrown at clis/12306/price.js:136

        { name: 'train-no', positional: true, required: true, help: 'Internal train_no from `12306 trains` (e.g. 24000000G10L)' },
        { name: 'from', required: true, help: 'Origin station (Chinese name, telecode, or pinyin) - must be a stop of this train' },
        { name: 'to', required: true, help: 'Destination station - must be a stop of this train' },
        { name: 'date', required: true, help: 'Departure date in YYYY-MM-DD' },
        { name: 'seat-types', default: 'OM9PA1A3A4FWZ', help: 'Seat-type letters to query (default covers the common classes). Examples: OM9 (二等/一等/商务), A1A3A4 (硬座/硬卧/软卧).' },
    ],
    columns: ['seat_code', 'seat_name', 'price', 'currency'],
    func: async (kwargs) => {
        const trainNo = String(kwargs['train-no'] ?? '').trim();
        if (!trainNo) throw new ArgumentError('<train-no> must not be empty');
        if (!TRAIN_NO_RE.test(trainNo)) {
            throw new ArgumentError(
                `<train-no> "${trainNo}" does not look like a 12306 internal train_no`,
                'Use the train_no field from `12306 trains` output (e.g. 24000000G10L), not the public code (G1).',
            );
        }
        const fromArg = String(kwargs.from ?? '').trim();
        const toArg = String(kwargs.to ?? '').trim();
        if (!fromArg) throw new ArgumentError('--from station must not be empty');
        if (!toArg) throw new ArgumentError('--to station must not be empty');
        const date = validateDate(kwargs.date);
        const seatTypes = String(kwargs['seat-types'] ?? '').trim() || 'OM9PA1A3A4FWZ';
        if (!SEAT_TYPES_RE.test(seatTypes)) {
            throw new ArgumentError('--seat-types must contain only 12306 seat letters/digits (A-Z, 0-9)');
        }

        const stations = await fetchStationBundle();
        const fromStation = resolveStation(stations, fromArg);
        const toStation = resolveStation(stations, toArg);
        if (fromStation.code === toStation.code) {
            throw new ArgumentError(`--from and --to must differ; both resolved to ${fromStation.name} (${fromStation.code})`);
        }

        const cookieHeader = await mintSession();
        const stops = await queryStopsForPrice(cookieHeader, trainNo, fromStation.code, toStation.code, date);
        const { fromNo, toNo } = pickStationNos(stops, fromStation.code, toStation.code, fromStation.name, toStation.name);
        const priceData = await queryPrice(cookieHeader, trainNo, fromNo, toNo, seatTypes, date);

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Pass `--from <station>` with a station name, telecode, or pinyin, e.g. `--from 北京南`.
  2. Check shell variables: ensure the value interpolating into --from is non-empty (`echo "$FROM"`).
  3. Verify the option spelling matches `--from` exactly.

Example fix

// before (FROM unset)
12306 price --train-no 24000000G10L --from "$FROM" --to 上海
// after
FROM=北京南; [ -n "$FROM" ] && 12306 price --train-no 24000000G10L --from "$FROM" --to 上海
Defensive patterns

Strategy: validation

Validate before calling

const from = String(opts.from ?? '').trim();
if (!from) throw new Error('--from station is required, e.g. --from 北京南');

Try / catch

try {
  await price({ 'train-no': tn, from, to, date });
} catch (e) {
  if (e instanceof ArgumentError && /--from station must not be empty/.test(e.message)) {
    console.error('Supply --from with a station name, telecode, or pinyin.');
  } else throw e;
}

Prevention

When it happens

Trigger: Calling `12306 price --train-no <tn> --to 上海` without `--from`, or with `--from ""` / whitespace-only value.

Common situations: Forgotten option in shell scripts; variables that expand to empty string (unset env var or empty JSON field); wrong option name (e.g. `--station-from`) so `from` is undefined.

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/b08b87e91e61cbf5. Report an issue: GitHub.