{"record":{"id":"e73d604456589f04","repo":"jackwener/OpenCLI","slug":"label-must-be-yyyy-mm-dd-got-json-stringify","errorCode":null,"errorMessage":"${label} must be YYYY-MM-DD, got ${JSON.stringify(value)}","messagePattern":"(.+?) must be YYYY-MM-DD, got (.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/booking/search.js","lineNumber":40,"sourceCode":"function normalizeNonNegativeInt(value, defaultValue, label, max) {\n  const raw = value ?? defaultValue;\n  const n = Number(raw);\n  if (!Number.isInteger(n) || n < 0) {\n    throw new ArgumentError(`${label} must be a non-negative integer`);\n  }\n  if (typeof max === 'number' && n > max) {\n    throw new ArgumentError(`${label} must be <= ${max}`);\n  }\n  return n;\n}\n\nfunction normalizeDate(value, label) {\n  const v = String(value || '').trim();\n  if (!v) {\n    throw new ArgumentError(`${label} is required (YYYY-MM-DD)`);\n  }\n  if (!DATE_RE.test(v)) {\n    throw new ArgumentError(`${label} must be YYYY-MM-DD, got ${JSON.stringify(value)}`);\n  }\n  const [year, month, day] = v.split('-').map(Number);\n  const d = new Date(Date.UTC(year, month - 1, day));\n  if (\n    Number.isNaN(d.getTime()) ||\n    d.getUTCFullYear() !== year ||\n    d.getUTCMonth() !== month - 1 ||\n    d.getUTCDate() !== day\n  ) {\n    throw new ArgumentError(`${label} is not a valid calendar date: ${v}`);\n  }\n  return v;\n}\n\nfunction normalizeCurrency(value) {\n  if (value == null || value === '') return '';\n  const v = String(value).trim().toUpperCase();\n  if (!/^[A-Z]{3}$/.test(v)) {","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/booking/search.js#L22-L58","documentation":"normalizeDate validates that a date parameter matches the strict YYYY-MM-DD format before building the search URL. It throws ArgumentError when the value is non-empty but does not satisfy /^\\d{4}-\\d{2}-\\d{2}$/. This rejects formats like MM/DD/YYYY, ISO timestamps, or relative dates so downstream URL construction only ever sees canonical dates.","triggerScenarios":"Calling the search command with checkin or checkout values like '08/28/2026', '2026-8-28', '2026-08-28T00:00:00Z', 'today+7', or a JS Date object stringified to a non-ISO form; any truthy value whose String() form fails DATE_RE.","commonSituations":"Passing a Date object instead of a formatted string; using locale-formatted dates from a UI picker (e.g. DD/MM/YYYY); supplying unix timestamps or 'now'/'tomorrow' shortcuts; copying dates with trailing time components from API responses.","solutions":["Reformat the value to strict YYYY-MM-DD (zero-padded month and day) before calling, e.g. with new Date(...).toISOString().slice(0, 10)","Strip any time component: take the first 10 characters of an ISO string","Convert Date objects via toISOString().slice(0,10) rather than template-string interpolation","Verify the locale of the source picker and reorder DD/MM/YYYY parts into YYYY-MM-DD"],"exampleFix":"// before\nconst checkin = new Date();\nawait search(page, { checkin, checkout: '2026-09-01' });\n// after\nconst checkin = new Date().toISOString().slice(0, 10);\nawait search(page, { checkin, checkout: '2026-09-01' });","handlingStrategy":"validation","validationCode":"function isValidDateString(v) {\n  return typeof v === 'string' && /^\\d{4}-\\d{2}-\\d{2}$/.test(v);\n}\nif (!isValidDateString(checkin) || !isValidDateString(checkout)) {\n  throw new Error('checkin/checkout must be YYYY-MM-DD strings');\n}","typeGuard":"function isYYYYMMDD(v) {\n  return typeof v === 'string' && /^\\d{4}-\\d{2}-\\d{2}$/.test(v);\n}","tryCatchPattern":"try {\n  await search(page, { destination, checkin, checkout });\n} catch (e) {\n  if (/must be YYYY-MM-DD/.test(e.message)) {\n    checkin = new Date(checkin).toISOString().slice(0, 10);\n    checkout = new Date(checkout).toISOString().slice(0, 10);\n  } else throw e;\n}","preventionTips":["Always produce dates via toISOString().slice(0, 10), never template interpolation of Date objects","Zero-pad month and day when building date strings manually","Store dates in config as canonical YYYY-MM-DD strings","Unit-test any date-generation helper against the strict format"],"tags":["validation","argument-error","date-format"],"backgroundTag":"invalid-date-format","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}