Currency filter crashes on undefined record field during SSE cache update

https://sonarly.com/issue/8335?type=bug

isMatchingCurrencyFilter crashes with TypeError when a record's currency field is undefined/null, breaking real-time SSE updates on the Opportunities page.

Fix: The fix adds a null/undefined guard at the top of `isMatchingCurrencyFilter` in `packages/twenty-shared/src/utils/filter/utils/isMatchingCurrencyFilter.ts`.

**Two changes were made to the function:**

1. The `value` parameter type was widened to include `null | undefined`, accurately reflecting what can be passed at runtime (since `record[filterKey]` in `isRecordMatchingFilter` returns `undefined` for unset composite fields).

2. An early return of `false` was added when `value` is `undefined` or `null`, using the existing `isDefined` utility that is already imported and used elsewhere in the file.

```typescript file=packages/twenty-shared/src/utils/filter/utils/isMatchingCurrencyFilter.ts lines=70-86
export const isMatchingCurrencyFilter = ({
  currencyFilter,
  value,
}: {
  currencyFilter: CurrencyFilter;
  value:
    | {
        amountMicros?: number | null;
        currencyCode?: string | null;
      }
    | null
    | undefined;
}) => {
  if (!isDefined(value)) {
    return false;
  }
  // ... rest of function
```

**Why `return false`?** A record with an unset currency field does not match a currency filter — this is semantically correct (e.g., a filter for `currencyCode: { in: ['USD'] }` should not match a record that has no currency set). This mirrors how `isMatchingAmountMicrosFilter` already handles `undefined` values for the `gt`/`gte`/`lt`/`lte` cases.
This commit is contained in:
Sonarly Claude Code
2026-03-04 03:27:45 +00:00
parent 07dd27f6c4
commit 65dc90e2b9
@@ -72,11 +72,18 @@ export const isMatchingCurrencyFilter = ({
value,
}: {
currencyFilter: CurrencyFilter;
value: {
amountMicros?: number | null;
currencyCode?: string | null;
};
value:
| {
amountMicros?: number | null;
currencyCode?: string | null;
}
| null
| undefined;
}) => {
if (!isDefined(value)) {
return false;
}
const shouldMatchCurrencyCodeFilter = isDefined(currencyFilter.currencyCode);
const shouldMatchAmountMicrosFilter = isDefined(currencyFilter.amountMicros);