{"record":{"id":"b238c698fcf5df3f","repo":"jackwener/OpenCLI","slug":"from-and-to-must-differ-got-fromcode-b238c6","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-round.js","lineNumber":49,"sourceCode":"        { name: 'to', required: true, positional: true, help: 'Arrival IATA code (e.g. NYC / JFK)' },\n        { name: 'depart', required: true, help: 'Outbound date (YYYY-MM-DD)' },\n        { name: 'return', required: true, help: 'Return 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 depart = parseIsoDate('depart', kwargs.depart);\n        const ret = parseIsoDate('return', kwargs.return);\n        if (depart >= ret) {\n            throw new ArgumentError(`--depart must be before --return (got ${depart} .. ${ret})`);\n        }\n        const limit = parseListLimit(kwargs.limit);\n\n        const searchUrl = buildFlightRoundSearchUrl(fromCode, toCode, depart, ret);\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());","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/trip/flight-round.js#L31-L67","documentation":"ArgumentError thrown by input validation in the round-trip flight command: after both --from and --to are parsed as IATA codes they are equal, which would produce a meaningless search (departing and arriving at the same airport). The library rejects it up front before any network request.","triggerScenarios":"Invoking the Trip.com flight-round command with identical origin and destination, e.g. --from PEK --to PEK, or codes that normalize to the same airport.","commonSituations":"Script variable mixups where from and to are populated from the same source; typo where both flags got the same value; users expecting multi-city search but using round-trip command.","solutions":["Pass two different IATA codes for --from and --to","Check the script/config that fills these flags for a copy-paste or variable-shadowing bug","If you truly need same-airport segments, use a different command (multi-city), not flight-round"],"exampleFix":"// before\ncli --trip flight-round --from PEK --to PEK --depart 2026-09-01 --return 2026-09-08\n// after\ncli --trip flight-round --from PEK --to SHA --depart 2026-09-01 --return 2026-09-08","handlingStrategy":"validation","validationCode":"function validRoundTrip(from, to) {\n    const f = String(from).trim().toUpperCase();\n    const t = String(to).trim().toUpperCase();\n    return /^[A-Z]{3}$/.test(f) && /^[A-Z]{3}$/.test(t) && f !== t;\n}\nif (!validRoundTrip(from, to)) throw new Error('--from and --to must be different IATA codes');","typeGuard":"function isDistinctIataPair(from, to): boolean {\n    return typeof from === 'string' && typeof to === 'string'\n        && from.trim().toUpperCase() !== to.trim().toUpperCase();\n}","tryCatchPattern":"try {\n    await runFlightRound({ from, to, depart, ret });\n} catch (e) {\n    if (e instanceof ArgumentError && /must differ/.test(e.message)) {\n        console.error(`Bad route: ${e.message}. Provide two different airports.`);\n    } else { throw e; }\n}","preventionTips":["Validate from !== to in the calling script before invoking the CLI","Load route pairs from checked config, not ad-hoc variables","Echo the expanded values in logs so mixups are visible"],"tags":["argument-validation","input-error","cli","trip-com"],"backgroundTag":"invalid-argument-value","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}