jackwener/OpenCLI · error · ArgumentError
--from and --to must differ (got ${fromCode})
Error message
--from and --to must differ (got ${fromCode}) What it means
An ArgumentError raised by the ctrip flight-round CLI argument validation: the parsed --from and --from IATA codes are identical, which would make a round-trip search nonsensical (Ctrip rejects same-origin round trips). parseIataCode normalizes both values before comparing, so 'PEK' vs 'pek' still matches and throws.
Source
Thrown at clis/ctrip/flight-round.js:69
{ name: 'from', required: true, positional: true, help: 'Departure IATA code (e.g. BJS / PEK)' },
{ name: 'to', required: true, positional: true, help: 'Arrival IATA code (e.g. SHA / PVG)' },
{ name: 'depart', required: true, help: 'Outbound date (YYYY-MM-DD)' },
{ name: 'return', required: true, help: 'Return date (YYYY-MM-DD), on or after depart' },
{ name: 'limit', default: 20, help: 'Number of flights (1-50)' },
],
columns: [
'rank',
'airline', 'flightNo', 'aircraft',
'departureTime', 'departureAirport',
'arrivalTime', 'arrivalAirport', 'terminal',
'price', 'currency', 'cabin',
'url',
],
func: async (page, kwargs) => {
const fromCode = parseIataCode('from', kwargs.from);
const toCode = parseIataCode('to', kwargs.to);
if (fromCode === toCode) {
throw new ArgumentError(`--from and --to must differ (got ${fromCode})`);
}
const depart = parseIsoDate('depart', kwargs.depart);
const ret = parseIsoDate('return', kwargs.return);
if (ret < depart) {
throw new ArgumentError(`--return (${ret}) must be on or after --depart (${depart})`);
}
const limit = parseListLimit(kwargs.limit);
const searchUrl =
`https://flights.ctrip.com/online/list/round-${fromCode.toLowerCase()}-${toCode.toLowerCase()}` +
`?depdate=${depart}_${ret}&cabin=Y_S_C_F&adult=1&child=0&infant=0`;
await page.goto(searchUrl);
const waitResult = await page.evaluate(WAIT_FOR_FLIGHTS_ROUND_JS);
if (waitResult === 'captcha') {
throw new AuthRequiredError('flights.ctrip.com', 'Ctrip is asking for a captcha; complete it in your browser session and retry');
}
if (waitResult !== 'content') {
throw new CommandExecutionError(`Ctrip round-trip flight page did not render flight cards (state=${String(waitResult)})`);View on GitHub (pinned to 49907e53dc)
Solutions
- Pass distinct origin and destination IATA codes for --from and --to.
- If building calls programmatically, validate fromCode !== toCode before invoking the CLI.
- Check for swapped or duplicated variables feeding the two flags in your script.
Example fix
// before
run(['flight-round', '--from', origin, '--to', origin, '--depart', d, '--return', r]);
// after
if (origin === destination) throw new Error('origin and destination must differ');
run(['flight-round', '--from', origin, '--to', destination, '--depart', d, '--return', r]); Defensive patterns
Strategy: validation
Validate before calling
const iata = (s) => String(s || '').trim().toUpperCase();
if (iata(from) === iata(to)) throw new Error('origin and destination IATA codes must differ'); Type guard
function isDistinctRoute(from, to) { return String(from).trim().toUpperCase() !== String(to).trim().toUpperCase(); } Try / catch
try { await cli(['flight-round', args]); } catch (e) { if (e instanceof ArgumentError) { console.error('usage:', e.message); process.exitCode = 2; } else throw e; } Prevention
- Validate origin !== destination before invoking flight-round.
- Normalize IATA codes (trim + uppercase) in your own input pipeline.
- Avoid defaulting both --from and --to from the same config field.
- Use the ARGUMENT exit code to distinguish usage bugs from runtime failures in CI.
When it happens
Trigger: Calling the flight-round command where kwargs.from and kwargs.to resolve to the same 3-letter IATA code, e.g. `--from PEK --to PEK` or `--from pek --to PEK`.
Common situations: Programmatic loop building routes where origin/destination variables were accidentally set from the same field; default values filled in for both flags; copy-paste mistakes in shell scripts.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- --from and --to must differ (got ${fromCity})
- tid must be a numeric thread id
- --return (${ret}) must be on or after --depart (${depart})
- --from and --to must differ (got ${fromName})
- Unknown --since "${sinceKey}". Valid: ${Object.keys(SINCE).j
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/8c969715eccc99be.
Report an issue: GitHub.