From e310c42bbfb4d39946ff05c50b9aff56f55ffa1c Mon Sep 17 00:00:00 2001 From: Sonarly Claude Code Date: Fri, 6 Mar 2026 13:21:46 +0000 Subject: [PATCH] Missing date validation in FormDateFieldInput crashes workflow editor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://sonarly.com/issue/4345?type=bug The `useParsePlainDateToDateInputString` hook calls `format()` from date-fns without validating that `parse()` returned a valid date, causing a `RangeError: Invalid time value` when a workflow step's date field contains a value not in `yyyy-MM-dd` format. Fix: Added `isValid()` checks from date-fns to the two Date formatting hooks that were missing them, matching the existing pattern in the DateTime equivalent hook (`useParseJSDateToIMaskDateTimeInputString`): **1. `useParsePlainDateToDateInputString.ts`** — Added `isValid(parsedDate)` check after `parse()` and before `format()`. When the input plain date string doesn't match `yyyy-MM-dd` format, `parse()` returns an Invalid Date. The new guard returns `''` instead of letting `format()` throw `RangeError: Invalid time value`. This is the primary fix for the Sentry error, as this function is called in `FormDateFieldInput`'s `useState` initializer. **2. `useParseJSDateToIMaskDateInputString.ts`** — Added `isDefined(jsDate) || !isValid(jsDate)` check before `format()`, exactly mirroring the guard in `useParseJSDateToIMaskDateTimeInputString`. This is a defensive fix for the same class of bug in the IMask formatting callback used by `DatePickerInput`. Both changes return `''` (empty string) for invalid dates, which is the same behavior the DateTime hooks use. The calling components already handle empty strings gracefully — `FormDateFieldInput` shows a placeholder, and IMask treats empty as a cleared value. --- .../date/hooks/useParseJSDateToIMaskDateInputString.ts | 7 ++++++- .../date/hooks/useParsePlainDateToDateInputString.ts | 6 +++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/twenty-front/src/modules/ui/input/components/internal/date/hooks/useParseJSDateToIMaskDateInputString.ts b/packages/twenty-front/src/modules/ui/input/components/internal/date/hooks/useParseJSDateToIMaskDateInputString.ts index 52977e63995..8b809f068c0 100644 --- a/packages/twenty-front/src/modules/ui/input/components/internal/date/hooks/useParseJSDateToIMaskDateInputString.ts +++ b/packages/twenty-front/src/modules/ui/input/components/internal/date/hooks/useParseJSDateToIMaskDateInputString.ts @@ -1,12 +1,17 @@ import { useDateTimeFormat } from '@/localization/hooks/useDateTimeFormat'; -import { format } from 'date-fns'; +import { format, isValid } from 'date-fns'; +import { isDefined } from 'twenty-shared/utils'; import { getDateFormatStringForDatePickerInputMask } from '~/utils/date-utils'; export const useParseJSDateToIMaskDateInputString = () => { const { dateFormat } = useDateTimeFormat(); const parseIMaskJSDateIMaskDateInputString = (jsDate: Date) => { + if (!isDefined(jsDate) || !isValid(jsDate)) { + return ''; + } + const parsingFormat = getDateFormatStringForDatePickerInputMask(dateFormat); const formattedDate = format(jsDate, parsingFormat); diff --git a/packages/twenty-front/src/modules/ui/input/components/internal/date/hooks/useParsePlainDateToDateInputString.ts b/packages/twenty-front/src/modules/ui/input/components/internal/date/hooks/useParsePlainDateToDateInputString.ts index 131929c5b47..26e4f6bce57 100644 --- a/packages/twenty-front/src/modules/ui/input/components/internal/date/hooks/useParsePlainDateToDateInputString.ts +++ b/packages/twenty-front/src/modules/ui/input/components/internal/date/hooks/useParsePlainDateToDateInputString.ts @@ -1,6 +1,6 @@ import { useDateTimeFormat } from '@/localization/hooks/useDateTimeFormat'; -import { format, parse } from 'date-fns'; +import { format, isValid, parse } from 'date-fns'; import { DATE_TYPE_FORMAT } from 'twenty-shared/constants'; import { getDateFormatStringForDatePickerInputMask } from '~/utils/date-utils'; @@ -12,6 +12,10 @@ export const useParsePlainDateToDateInputString = () => { const parsedDate = parse(plainDate, DATE_TYPE_FORMAT, new Date()); + if (!isValid(parsedDate)) { + return ''; + } + const formattedDate = format(parsedDate, parsingFormat); return formattedDate;