{"record":{"id":"5386590ca9f1d461","repo":"jackwener/OpenCLI","slug":"name-is-required-3-letter-iata-code-e-g-pe","errorCode":null,"errorMessage":"--${name} is required (3-letter IATA code, e.g. PEK, SHA)","messagePattern":"--(.+?) is required \\(3-letter IATA code, e\\.g\\. PEK, SHA\\)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/ctrip/utils.js","lineNumber":237,"sourceCode":"    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}`);\n    }\n    // Cross-check via UTC date math so 2026-02-30 doesn't pass.\n    const parsed = new Date(Date.UTC(year, month - 1, day));\n    if (parsed.getUTCFullYear() !== year || parsed.getUTCMonth() !== month - 1 || parsed.getUTCDate() !== day) {\n        throw new ArgumentError(`--${name} is not a real calendar date: ${value}`);\n    }\n    return value;\n}\n\n/**\n * Validate a 3-letter IATA airport / metro code, return uppercase.\n * Ctrip URL accepts both single-airport (PEK / PVG) and metro-group (BJS / SHA) codes.\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. PEK, SHA)`);\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\n/**\n * Validate a numeric Ctrip city ID (returned by `ctrip search` / `ctrip hotel-suggest`).\n */\nexport function parseCityId(raw) {\n    if (raw === undefined || raw === null || raw === '' || String(raw).trim() === '') {\n        throw new ArgumentError('--city is required (numeric city ID from `ctrip search` or `ctrip hotel-suggest`)');\n    }\n    try {\n        return parseStrictPositiveInteger('city', raw);\n    } catch {","sourceCodeStart":219,"sourceCodeEnd":255,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/ctrip/utils.js#L219-L255","documentation":"parseIataCode throws this ArgumentError when the airport/metro code option is missing (undefined, null, or empty string). Flight commands require both --from and --to codes, and the library refuses to guess. Valid codes are 3-letter IATA airport codes (PEK, PVG) or metro-group codes (BJS, SHA).","triggerScenarios":"Calling parseIataCode(name, raw) from --fromCode/--toCode paths when the flag was omitted or passed empty, e.g. `ctrip flight --to SHA` without --from.","commonSituations":"User doesn't know the code and omits the flag; empty env var feeds the flag; script builds args conditionally and drops one; user passes a city name ('Beijing') instead of a code.","solutions":["Provide the flag with a 3-letter code, e.g. --from PEK --to SHA","Look up codes with `ctrip search` (city suggestions include ids) or an IATA lookup","Fix the empty env/shell variable feeding the flag","Use metro codes (BJS for Beijing, SHA for Shanghai) when unsure of the specific airport"],"exampleFix":"// before\nctrip flight --to SHA\n// after\nctrip flight --from PEK --to SHA --date 2026-09-01","handlingStrategy":"validation","validationCode":"function requireIata(value, name) {\n  const v = String(value ?? '').trim().toUpperCase();\n  if (!/^[A-Z]{3}$/.test(v)) throw new Error(`--${name} must be a 3-letter IATA code`);\n  return v;\n}","typeGuard":"function isIataCode(v) {\n  return typeof v === 'string' && /^[A-Za-z]{3}$/.test(v.trim());\n}","tryCatchPattern":"try {\n  const from = parseIataCode('from', rawFrom);\n} catch (err) {\n  if (err instanceof ArgumentError && /is required/.test(err.message)) {\n    // prompt the user or fall back to a default origin\n  }\n  throw err;\n}","preventionTips":["Always pass both --from and --to with 3-letter codes","Look up codes via `ctrip search` before running flight commands","Use metro codes (BJS/SHA) when the specific airport is flexible","Guard env-var-driven flags against empty values in scripts"],"tags":["argument-validation","cli","missing-argument","iata"],"backgroundTag":"missing-required-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}