{"record":{"id":"cf73326fce6fddb9","repo":"makeplane/plane","slug":"unsupported-time-unit-unit","errorCode":null,"errorMessage":"Unsupported time unit: ${unit}","messagePattern":"Unsupported time unit: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/utils/src/datetime.ts","lineNumber":439,"sourceCode":"  const [amountStr, unit] = value.split(\"_\");\n  const amount = parseInt(amountStr, 10);\n  if (isNaN(amount)) {\n    throw new Error(`Invalid relative amount: ${amountStr}`);\n  }\n  const date = new Date();\n\n  switch (unit) {\n    case \"days\":\n      date.setDate(date.getDate() + amount);\n      break;\n    case \"weeks\":\n      date.setDate(date.getDate() + amount * 7);\n      break;\n    case \"months\":\n      date.setMonth(date.getMonth() + amount);\n      break;\n    default:\n      throw new Error(`Unsupported time unit: ${unit}`);\n  }\n\n  return date;\n};\n\n/**\n * Parses a date filter string and returns the comparison type and date\n * @param filterValue The date filter string (e.g., \"1_weeks;after;fromnow\" or \"2024-12-01;after\")\n * @returns Object containing the comparison type and target date\n */\nexport const parseDateFilter = (filterValue: string): { type: \"after\" | \"before\"; date: Date } => {\n  const parts = filterValue.split(\";\");\n  const dateStr = parts[0];\n  const type = parts[1] as \"after\" | \"before\";\n\n  let date: Date;\n  if (dateStr.includes(\"_\")) {\n    // Handle relative dates (e.g., \"1_weeks;after;fromnow\")","sourceCodeStart":421,"sourceCodeEnd":457,"githubUrl":"https://github.com/makeplane/plane/blob/1c8a60f858d8472aa56e29994ec1c7926da2c6ce/packages/utils/src/datetime.ts#L421-L457","documentation":"Thrown by the default branch of processRelativeDate's switch on the unit segment. Only 'days', 'weeks', and 'months' are implemented; any other unit string (years, hours, quarters, typos) hits default and raises this. The unit comes from the second half of the `<amount>_<unit>` token.","triggerScenarios":"processRelativeDate('1_years'), processRelativeDate('2_week'), processRelativeDate('3_hrs') — anything whose unit is not exactly 'days'/'weeks'/'months'.","commonSituations":"Token producer uses a different vocabulary (years, quarters); typo in a hand-authored token; mismatch between the UI labels and the supported unit strings.","solutions":["Map unsupported units to supported ones before calling (years -> 12 months, quarters -> 3 months).","Extend the switch to handle the additional unit if it should be first-class.","Validate the unit against an allowlist before invoking processRelativeDate."],"exampleFix":"// before\nprocessRelativeDate(`${n}_years`)\n\n// after\nprocessRelativeDate(`${n * 12}_months`)","handlingStrategy":"validation","validationCode":"const UNITS = ['days','weeks','months'] as const;\nfunction supportedUnit(u: string): boolean { return (UNITS as readonly string[]).includes(u); }","typeGuard":"type Unit = typeof UNITS[number];\nfunction isUnit(u: string): u is Unit { return (UNITS as readonly string[]).includes(u); }","tryCatchPattern":"try { processRelativeDate(v); } catch (e) { if (/Unsupported time unit/.test((e as Error).message)) { /* map or skip */ } else throw e; }","preventionTips":["Map years->months, quarters->3 months upstream","Keep unit strings in a single shared constant","Extend the switch deliberately when adding a unit"],"tags":["datetime","filters","validation","parsing"],"backgroundTag":null,"analyzedSha":"1c8a60f858d8472aa56e29994ec1c7926da2c6ce","analyzedAt":"2026-08-12T14:44:31.636Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}