{"record":{"id":"b8c68ace60835085","repo":"jackwener/OpenCLI","slug":"date-must-be-yyyy-mm-dd-date","errorCode":null,"errorMessage":"Date must be YYYY-MM-DD: ${date}","messagePattern":"Date must be YYYY-MM-DD: (.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/mercury/utils.js","lineNumber":69,"sourceCode":"    if (!/^\\d+(\\.\\d{1,2})?$/.test(amount) || Number(amount) <= 0) {\n        throw new ArgumentError(`Amount must be a positive number with up to two decimals: ${amount}`);\n    }\n    return amount;\n}\n\nfunction parseCurrency(kwargs) {\n    const currency = optionalString(kwargs, 'currency', 'CNY').toUpperCase();\n    if (!/^[A-Z]{3}$/.test(currency)) {\n        throw new ArgumentError(`Currency must be a three-letter ISO currency code: ${currency}`);\n    }\n    return currency;\n}\n\nfunction parseDate(kwargs) {\n    const date = requireString(kwargs, 'date');\n    const match = date.match(/^(\\d{4})-(\\d{2})-(\\d{2})$/);\n    if (!match) {\n        throw new ArgumentError(`Date must be YYYY-MM-DD: ${date}`);\n    }\n    const year = Number(match[1]);\n    const month = Number(match[2]);\n    const day = Number(match[3]);\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(`Date must be a real calendar date: ${date}`);\n    }\n    return date;\n}\n\nfunction parseOcrWaitSeconds(kwargs) {\n    const raw = optionalString(kwargs, 'ocr-wait-seconds', '8');\n    if (!/^\\d+$/.test(raw)) {\n        throw new ArgumentError(`ocr-wait-seconds must be a non-negative integer: ${raw}`);\n    }\n    return Number(raw);\n}","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/mercury/utils.js#L51-L87","documentation":"parseDate requires the date in strict YYYY-MM-DD form via regex ^\\d{4}-\\d{2}-\\d{2}$. Any other format — slashes, missing zero-padding, extra whitespace, timestamps — throws this ArgumentError before the real-calendar check runs.","triggerScenarios":"dates like '2026/08/01', '2026-8-1', '01-08-2026', '2026-08-01T00:00:00Z', '2026-8-01' or values with leading/trailing spaces.","commonSituations":"Locale-formatted dates pasted from spreadsheets (MM/DD/YYYY); programmatic callers passing ISO datetime strings; shell interpolation inserting whitespace; users from slash-date locales.","solutions":["Format the date as YYYY-MM-DD with zero-padded month and day: 2026-08-01.","If you have a Date object, use date.toISOString().slice(0, 10).","Trim the value and strip any time component before passing.","Normalize MM/DD/YYYY or DD/MM/YYYY inputs by reordering parts before invoking."],"exampleFix":"// before\n--date \"08/01/2026\"\n// after\n--date \"2026-08-01\"","handlingStrategy":"validation","validationCode":"function isIsoDateShape(d) {\n  return /^\\d{4}-\\d{2}-\\d{2}$/.test(String(d).trim());\n}\n// from a Date object:\nconst iso = new Date().toISOString().slice(0, 10);","typeGuard":null,"tryCatchPattern":"try {\n  await reimburse({ date });\n} catch (e) {\n  if (e instanceof ArgumentError && e.message.includes('Date must be YYYY-MM-DD')) {\n    console.error(`Got '${date}'. Use zero-padded YYYY-MM-DD, e.g. 2026-08-01`);\n  } else throw e;\n}","preventionTips":["Generate dates with toISOString().slice(0,10)","Never pass locale-formatted (MM/DD/YYYY) strings directly","Trim user input before forwarding","Keep dates as ISO strings end-to-end in scripts"],"tags":["argument-validation","date-format","input-validation","cli"],"backgroundTag":"invalid-input-format","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}