jackwener/OpenCLI · error · ArgumentError
--${name} has invalid month/day: ${value}
Error message
--${name} has invalid month/day: ${value} What it means
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).
Source
Thrown at clis/ctrip/utils.js:221
/**
* Validate YYYY-MM-DD and return the canonical string. Rejects out-of-range
* month/day, malformed input, and silent NaN. Does NOT coerce or shift timezones.
*/
export function parseIsoDate(name, raw) {
if (raw === undefined || raw === null || raw === '' || String(raw).trim() === '') {
throw new ArgumentError(`--${name} is required (YYYY-MM-DD)`);
}
const value = String(raw);
const m = ISO_DATE_RE.exec(value);
if (!m) {
throw new ArgumentError(`--${name} must be YYYY-MM-DD, got ${JSON.stringify(raw)}`);
}
const year = Number(m[1]);
const month = Number(m[2]);
const day = Number(m[3]);
if (month < 1 || month > 12 || day < 1 || day > 31) {
throw new ArgumentError(`--${name} has invalid month/day: ${value}`);
}
// Cross-check via UTC date math so 2026-02-30 doesn't pass.
const parsed = new Date(Date.UTC(year, month - 1, day));
if (parsed.getUTCFullYear() !== year || parsed.getUTCMonth() !== month - 1 || parsed.getUTCDate() !== day) {
throw new ArgumentError(`--${name} is not a real calendar date: ${value}`);
}
return value;
}
/**
* Validate a 3-letter IATA airport / metro code, return uppercase.
* Ctrip URL accepts both single-airport (PEK / PVG) and metro-group (BJS / SHA) codes.
*/
export function parseIataCode(name, raw) {
if (raw === undefined || raw === null || raw === '') {
throw new ArgumentError(`--${name} is required (3-letter IATA code, e.g. PEK, SHA)`);
}
const value = String(raw).trim().toUpperCase();View on GitHub (pinned to 49907e53dc)
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
Example fix
// before
const date = `${y}-${d.getMonth()}-${d.getDate()}`; // month may be 0-11
// after
const m = String(d.getMonth() + 1).padStart(2, '0');
const day = String(d.getDate()).padStart(2, '0');
const date = `${y}-${m}-${day}`; Defensive patterns
Strategy: validation
Validate before calling
function checkRange(y, m, d) {
if (m < 1 || m > 12) throw new Error(`month out of range: ${m}`);
if (d < 1 || d > 31) throw new Error(`day out of range: ${d}`);
} Type guard
function isInRange(n, min, max) {
return Number.isInteger(n) && n >= min && n <= max;
} Try / catch
try {
const date = parseIsoDate('ret', raw);
} catch (err) {
if (err instanceof ArgumentError && /invalid month\/day/.test(err.message)) {
// re-derive the date programmatically instead of hand-typed input
}
throw err;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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()).
Related errors
- ${label} is required (YYYY-MM-DD)
- --${name} must be YYYY-MM-DD, got ${JSON.stringify(raw)}
- huodongxing ${label} must be a valid YYYY-MM-DD date
- Date must be YYYY-MM-DD: ${date}
- --${name} must be YYYY-MM-DD, got ${JSON.stringify(raw)}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/bff256aecb3d7fa0.
Report an issue: GitHub.