{"record":{"id":"bff256aecb3d7fa0","repo":"jackwener/OpenCLI","slug":"name-has-invalid-month-day-value","errorCode":null,"errorMessage":"--${name} has invalid month/day: ${value}","messagePattern":"--(.+?) has invalid month/day: (.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/ctrip/utils.js","lineNumber":221,"sourceCode":"\n/**\n * Validate YYYY-MM-DD and return the canonical string. Rejects out-of-range\n * month/day, malformed input, and silent NaN. Does NOT coerce or shift timezones.\n */\nexport function parseIsoDate(name, raw) {\n    if (raw === undefined || raw === null || raw === '' || String(raw).trim() === '') {\n        throw new ArgumentError(`--${name} is required (YYYY-MM-DD)`);\n    }\n    const value = String(raw);\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}`);\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();","sourceCodeStart":203,"sourceCodeEnd":239,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/ctrip/utils.js#L203-L239","documentation":"parseIsoDate throws this ArgumentError after the regex matches but the numeric month/day is out of range: month not in 1–12 or day not in 1–31. This is a cheap first-range check before the exact calendar cross-check (see the next error for impossible dates like Feb 30).","triggerScenarios":"Calling parseIsoDate(name, raw) with pattern-valid but range-invalid values such as 2026-13-01, 2026-00-10, 2026-05-32, or 2026-06-00.","commonSituations":"Swapped day/month fields producing month 25+; typo in month digit; off-by-one when generating dates programmatically (0-based month from JS Date.getMonth()).","solutions":["Correct the month to 1–12 and day to 1–31 (respecting the real month length)","When generating dates in JS, use getMonth()+1 — getMonth() is 0-based","Swap day/month if you intended the other order","Validate generated dates before passing them to the CLI"],"exampleFix":"// before\nconst date = `${y}-${d.getMonth()}-${d.getDate()}`; // month may be 0-11\n// after\nconst m = String(d.getMonth() + 1).padStart(2, '0');\nconst day = String(d.getDate()).padStart(2, '0');\nconst date = `${y}-${m}-${day}`;","handlingStrategy":"validation","validationCode":"function checkRange(y, m, d) {\n  if (m < 1 || m > 12) throw new Error(`month out of range: ${m}`);\n  if (d < 1 || d > 31) throw new Error(`day out of range: ${d}`);\n}","typeGuard":"function isInRange(n, min, max) {\n  return Number.isInteger(n) && n >= min && n <= max;\n}","tryCatchPattern":"try {\n  const date = parseIsoDate('ret', raw);\n} catch (err) {\n  if (err instanceof ArgumentError && /invalid month\\/day/.test(err.message)) {\n    // re-derive the date programmatically instead of hand-typed input\n  }\n  throw err;\n}","preventionTips":["Remember JS getMonth() is 0-based — add 1 when formatting","Swap day/month if you used the other convention","Generate dates with date libraries instead of string templates","Validate dates in scripts before passing them to the CLI"],"tags":["argument-validation","date-format","cli"],"backgroundTag":"invalid-date-format","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}