jackwener/OpenCLI · warning · ArgumentError
--from and --to must differ (got ${fromCode})
Error message
--from and --to must differ (got ${fromCode}) What it means
A pure client-side ArgumentError raised before any network activity: the `ctrip flight` command requires --from and --to to be different IATA codes, because the oneway results URL (`oneway-<from>-<to>`) is meaningless when both endpoints are the same and Ctrip would not serve a useful list. The message echoes the offending code so you can see which value was reused.
Source
Thrown at clis/ctrip/flight.js:172
args: [
{ 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: 'date', required: true, help: 'Departure date (YYYY-MM-DD)' },
{ name: 'limit', default: DEFAULT_LIMIT, help: `Number of flights (${MIN_LIMIT}-${MAX_LIMIT})` },
],
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 date = parseIsoDate('date', kwargs.date);
const limit = parseFlightLimit(kwargs.limit);
const searchUrl =
`https://flights.ctrip.com/online/list/oneway-${fromCode.toLowerCase()}-${toCode.toLowerCase()}` +
`?depdate=${date}&cabin=Y_S_C_F&adult=1&child=0&infant=0`;
if (typeof page?.startNetworkCapture !== 'function' ||
typeof page?.readNetworkCapture !== 'function' ||
!await page.startNetworkCapture(CAPTURE_PATTERN)) {
throw new CommandExecutionError('Ctrip flight requires browser response interception');
}
await page.readNetworkCapture();
await page.goto(searchUrl);
// The initial document can finish before the large batchSearch body.
// The first rendered card is only a readiness signal; row data still
// comes exclusively from the structured response below.
const readiness = await page.evaluate(WAIT_FOR_BATCH_CAPTURE_JS);View on GitHub (pinned to 49907e53dc)
Solutions
- Pass two distinct IATA codes, e.g. `ctrip flight BJS SHA --date 2026-09-01`.
- If building routes in a script, filter out pairs where from === to before invoking the command.
- If you actually need flights departing from one airport and returning, use the sibling `flight-round` (round-trip) command instead of oneway.
Example fix
// before
await cliRun(['flight', 'PEK', 'PEK', '--date', '2026-09-01']);
// after: guard before calling
if (from === to) throw new Error('from and to must differ');
await cliRun(['flight', from, to, '--date', '2026-09-01']); Defensive patterns
Strategy: validation
Validate before calling
function validateRoute(from, to) {
if (String(from).toUpperCase() === String(to).toUpperCase()) {
throw new Error(`route endpoints must differ (got ${from})`);
}
}
validateRoute(from, to); Try / catch
try {
const rows = await ctripFlight({ from, to, date });
} catch (e) {
if (e instanceof ArgumentError && e.message.includes('must differ')) {
console.error(`Bad route: ${e.message}`); process.exitCode = 2; return [];
}
throw e;
} Prevention
- Validate from !== to at the top of any script that builds route lists.
- Filter self-routes (from === to) out of programmatically generated pairs.
- Use the round-trip command for A→B→A needs instead of forcing oneway.
- Echo the full command line in logs so identical positional args are obvious.
When it happens
Trigger: Calling `ctrip flight BJS BJS --date ...` (or any identical from/to IATA codes, e.g. `PEK PEK`). The check compares parseIataCode('from') === parseIataCode('to') in the command's func at clis/ctrip/flight.js:171.
Common situations: Scripting a loop over routes where a placeholder variable was never replaced; typo where both positional args got the same city; generating routes programmatically and including self-routes by accident; testing the CLI with the same value twice to 'just see it run'.
Related errors
- archive snapshots url cannot be empty
- archive snapshots limit must be a positive integer
- archive snapshots limit must be <= 1000
- archive snapshots ${key} must be a digit-only timestamp (YYY
- bilibili unfollow target must be a valid space.bilibili.com/
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/8f61e2ce0b87c33f.
Report an issue: GitHub.