{"record":{"id":"5024934745792330","repo":"jackwener/OpenCLI","slug":"from-and-to-must-differ-got-fromcode-502493","errorCode":null,"errorMessage":"--from and --to must differ (got ${fromCode})","messagePattern":"--from and --to must differ \\(got (.+?)\\)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/trip/flight.js","lineNumber":48,"sourceCode":"        { name: 'from', required: true, positional: true, help: 'Departure IATA code (e.g. LON / LHR)' },\n        { name: 'to', required: true, positional: true, help: 'Arrival IATA code (e.g. NYC / JFK)' },\n        { name: 'date', required: true, help: 'Departure date (YYYY-MM-DD)' },\n        { name: 'limit', type: 'int', default: 20, help: 'Number of flights (1-50)' },\n    ],\n    columns: [\n        'rank',\n        'airline',\n        'departureTime', 'departureAirport',\n        'arrivalTime', 'arrivalAirport',\n        'duration', 'stops',\n        'price', 'currency',\n        'url',\n    ],\n    func: async (page, kwargs) => {\n        const fromCode = parseIataCode('from', kwargs.from);\n        const toCode = parseIataCode('to', kwargs.to);\n        if (fromCode === toCode) {\n            throw new ArgumentError(`--from and --to must differ (got ${fromCode})`);\n        }\n        const date = parseIsoDate('date', kwargs.date);\n        const limit = parseListLimit(kwargs.limit);\n\n        const searchUrl = buildFlightSearchUrl(fromCode, toCode, date);\n        await page.goto(searchUrl);\n        const waitResult = await page.evaluate(WAIT_FOR_FLIGHTS_JS);\n        if (waitResult === 'captcha') {\n            throw new AuthRequiredError('trip.com', 'Trip.com is asking for a verification; complete it in your browser session and retry');\n        }\n        if (waitResult !== 'content') {\n            throw new CommandExecutionError(`Trip.com flight page did not render flight cards (state=${String(waitResult)})`);\n        }\n        const raw = await page.evaluate(buildFlightExtractJs());\n        if (!Array.isArray(raw)) {\n            const reason = raw && typeof raw === 'object' && typeof raw.error === 'string'\n                && /^malformed flight card \\d+: [a-z /]+$/.test(raw.error)\n                ? `: ${raw.error}`","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/trip/flight.js#L30-L66","documentation":"This ArgumentError is thrown before any network call in clis/trip/flight.js when parseIataCode resolves --from and --to to the same IATA code. Trip.com one-way flight search is meaningless for identical origin and destination, so the command fails fast with the resolved code included in the message. It is an input validation error, not a runtime or site issue.","triggerScenarios":"Invoking the one-way flight command with --from and --set --to that normalize to the same IATA code, e.g. --from sfo --to SFO, or two aliases (city name and code) that resolve to the same airport.","commonSituations":"Copy-pasting the same code into both flags; case/format differences masking the equality ('sfo' vs 'SFO'); scripting that interpolates the same variable into both flags; users misunderstanding that origin and destination must be distinct airports.","solutions":["Check the command invocation and supply two different IATA codes for --from and --to.","Validate in a wrapper script that from !== to (after normalization to uppercase) before invoking the command.","If an airport pair is dynamically generated, guard against degenerate from==to pairs at generation time."],"exampleFix":"// before\nawait runTripFlight({ from: args.from, to: args.to }); // both 'SFO'\n// after\nconst from = args.from.trim().toUpperCase();\nconst to = args.to.trim().toUpperCase();\nif (from === to) throw new Error('--from and --to must differ');\nawait runTripFlight({ from, to });","handlingStrategy":"validation","validationCode":"const norm = (s) => String(s || '').trim().toUpperCase();\nconst from = norm(kwargs.from), to = norm(kwargs.to);\nif (!/^[A-Z]{3}$/.test(from) || !/^[A-Z]{3}$/.test(to)) throw new Error('from/to must be 3-letter IATA codes');\nif (from === to) throw new Error(`--from and --to must differ (got ${from})`);","typeGuard":"null","tryCatchPattern":"try {\n  await runTripFlight(args);\n} catch (e) {\n  if (e instanceof ArgumentError) {\n    console.error(`Bad arguments: ${e.message}`);\n    process.exitCode = 2;\n  } else throw e;\n}","preventionTips":["Normalize from/to to uppercase before comparing or passing.","Never interpolate the same variable into both --from and --to.","Add from!==to assertion in scripts that build commands dynamically.","Use unambiguous IATA codes rather than city aliases."],"tags":["argument-validation","input-error","flights","trip-com"],"backgroundTag":"invalid-argument-combination","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}