{"record":{"id":"1f62df7dcae08acf","repo":"jackwener/OpenCLI","slug":"name-must-be-a-3-letter-iata-code-got-json-1f62df","errorCode":null,"errorMessage":"--${name} must be a 3-letter IATA code, got ${JSON.stringify(raw)}","messagePattern":"--(.+?) must be a 3-letter IATA code, got (.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/trip/utils.js","lineNumber":23,"sourceCode":" * results client-side, so the browser-mode commands read the rendered DOM.\n * Flight rows are `.result-item` cards keyed by stable `data-testid` anchors\n * (`flights-name`, `stopInfoText`, `flight_price_*`).\n */\nimport { ArgumentError, CommandExecutionError } from '@jackwener/opencli/errors';\n\nconst MIN_LIMIT = 1;\nconst MAX_LIMIT = 50;\nconst ISO_DATE_RE = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\nconst POI_SEARCH_ENDPOINT = 'https://www.trip.com/restapi/soa2/14427/poiSearch';\nconst PACKAGE_SEARCH_ENDPOINT = 'https://www.trip.com/restapi/soa2/19866/FlightSelectSearch';\n\nexport function parseIataCode(name, raw) {\n    if (raw === undefined || raw === null || raw === '') {\n        throw new ArgumentError(`--${name} is required (3-letter IATA code, e.g. LON, NYC)`);\n    }\n    const value = String(raw).trim().toUpperCase();\n    if (!/^[A-Z]{3}$/.test(value)) {\n        throw new ArgumentError(`--${name} must be a 3-letter IATA code, got ${JSON.stringify(raw)}`);\n    }\n    return value;\n}\n\nexport function parseIsoDate(name, raw) {\n    if (raw === undefined || raw === null || raw === '') {\n        throw new ArgumentError(`--${name} is required (YYYY-MM-DD)`);\n    }\n    const value = String(raw).trim();\n    const m = ISO_DATE_RE.exec(value);\n    if (!m) {\n        throw new ArgumentError(`--${name} must be YYYY-MM-DD, got ${JSON.stringify(raw)}`);\n    }\n    const year = Number(m[1]);\n    const month = Number(m[2]);\n    const day = Number(m[3]);\n    if (month < 1 || month > 12 || day < 1 || day > 31) {\n        throw new ArgumentError(`--${name} has invalid month/day: ${value}`);","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/trip/utils.js#L5-L41","documentation":"parseIataCode validates a CLI argument as a 3-letter IATA airport/city code (e.g. LON, NYC). This error is thrown when the value is provided but is not exactly three uppercase ASCII letters after trimming and uppercasing. It is an ArgumentError meant to give the CLI user immediate, actionable feedback.","triggerScenarios":"Calling fromCode, toCode, or airport (which delegate to parseIataCode) with a value that, after String(raw).trim().toUpperCase(), fails /^[A-Z]{3}$/ — e.g. 'London', 'lo', 'LON ', 'L1A', numeric 123, or arrays/objects.","commonSituations":"Users type full city names ('London') instead of IATA codes; shell expands a value into multiple tokens ('NYC LON'); a variable is empty or contains a number; copy-pasted code includes trailing punctuation.","solutions":["Pass a valid 3-letter IATA code, e.g. --from LON --to NYC","If passing a city name, map it to its IATA code first (via airport lookup/search tooling)","Quote shell arguments so spaces don't split them, and ensure no trailing whitespace or stray characters","Check that the variable you interpolate actually contains the code, not an empty string, number, or object"],"exampleFix":"// before\nclis-trip flights --from London --to NYC\n// after\nclis-trip flights --from LON --to NYC","handlingStrategy":"validation","validationCode":"function isValidIata(v) {\n  return typeof v === 'string' && /^[A-Z]{3}$/.test(v.trim().toUpperCase());\n}\nif (!isValidIata(from)) throw new Error(`--from must be a 3-letter IATA code, got ${JSON.stringify(from)}`);","typeGuard":"function isIataCode(v) {\n  return typeof v === 'string' && /^[A-Z]{3}$/.test(v.trim().toUpperCase());\n}","tryCatchPattern":"import { ArgumentError } from 'clis/trip/utils.js';\ntry {\n  runTripCli(['flights', '--from', from, '--to', to]);\n} catch (err) {\n  if (err instanceof ArgumentError && /must be a 3-letter IATA code/.test(err.message)) {\n    console.error(`Bad airport code: ${err.message}. Use codes like LON, NYC.`);\n    process.exitCode = 2;\n  } else throw err;\n}","preventionTips":["Normalize input with String(raw).trim().toUpperCase() before passing","Maintain a lookup table mapping city names to IATA codes and validate against it","Quote shell arguments to prevent splitting on spaces","Validate flags in wrapper scripts before invoking the CLI"],"tags":["cli","argument-validation","iata-code"],"backgroundTag":"invalid-cli-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}