https://sonarly.com/issue/5117?type=bug
Editing a percentage-type number field (e.g., Opportunity probability) and clicking outside throws an unhandled error because the validation strips "%" but the subsequent cast receives the raw value still containing "%".
Fix: The fix is a one-line change in `NumberFieldInput.tsx`: pass `newValueEscaped` (the `%`-stripped value) to `castAsNumberOrNull` instead of `newValue` (the raw user input that may contain `%`).
**Before:**
```typescript file=packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/input/components/NumberFieldInput.tsx lines=29-36
if (fieldDefinition?.metadata?.settings?.type === 'percentage') {
const newValueEscaped = newValue.replaceAll('%', '');
if (!canBeCastAsNumberOrNull(newValueEscaped)) { // ✅ validates "75"
return { success: false };
}
const castedValue = castAsNumberOrNull(newValue); // ❌ casts "75%" — throws!
```
**After:**
```typescript file=packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/input/components/NumberFieldInput.tsx lines=29-36
if (fieldDefinition?.metadata?.settings?.type === 'percentage') {
const newValueEscaped = newValue.replaceAll('%', '');
if (!canBeCastAsNumberOrNull(newValueEscaped)) { // ✅ validates "75"
return { success: false };
}
const castedValue = castAsNumberOrNull(newValueEscaped); // ✅ casts "75"
```
The validation guard on line 32 already correctly used `newValueEscaped`, so the cast on line 36 must use the same variable. Previously, the guard would pass for `"75%"` (because it validated the escaped `"75"`), but then `castAsNumberOrNull("75%")` would be called — and since `+"75%"` evaluates to `NaN`, it would throw `Error: Cannot cast to number or null`. Now both the validation and the cast operate on the same `%`-stripped value, eliminating the mismatch.