mirror of
https://github.com/hyperdxio/hyperdx
synced 2026-04-21 13:37:15 +00:00
fix: guard formatNumber against non-numeric values (#1721)
## Summary Fixes #1510 **Root cause:** When a number format (e.g., Percent) is applied to table columns that contain non-numeric values, `formatNumber` doesn't catch non-empty strings. `numbro()` then produces NaN. The existing check `!value && value !== 0` catches `null`, `undefined`, and `NaN`, but NOT non-empty strings (which are truthy and pass through to `numbro()`). ## Changes - `packages/app/src/utils.ts`: Added `typeof value !== 'number' || isNaN(value)` guard that returns the raw value as a string instead of formatting it. ## Risk Assessment **Low** - Only adds a guard for an edge case. Numeric values are formatted exactly as before. Co-authored-by: Karl Power <85935352+karl-power@users.noreply.github.com>
This commit is contained in:
parent
4cb175d477
commit
3797e657d5
3 changed files with 28 additions and 0 deletions
5
.changeset/large-seas-clean.md
Normal file
5
.changeset/large-seas-clean.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"@hyperdx/app": patch
|
||||
---
|
||||
|
||||
fix: guard formatNumber against non-numeric values
|
||||
|
|
@ -264,6 +264,23 @@ describe('formatNumber', () => {
|
|||
expect(formatNumber(1234567, format)).toBe('1m');
|
||||
});
|
||||
});
|
||||
|
||||
describe('NaN handling', () => {
|
||||
it('returns "N/A" for NaN without options', () => {
|
||||
expect(formatNumber(NaN)).toBe('N/A');
|
||||
expect(formatNumber(NaN, { output: 'number', mantissa: 2 })).toBe('N/A');
|
||||
});
|
||||
|
||||
it('returns a string unchanged if a number cannot be parsed from it', () => {
|
||||
// @ts-expect-error not passing a number
|
||||
expect(formatNumber('not a number')).toBe('not a number');
|
||||
|
||||
expect(
|
||||
// @ts-expect-error not passing a number
|
||||
formatNumber('not a number', { output: 'number', mantissa: 2 }),
|
||||
).toBe('not a number');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('useLocalStorage', () => {
|
||||
|
|
|
|||
|
|
@ -760,6 +760,12 @@ export const formatNumber = (
|
|||
return 'N/A';
|
||||
}
|
||||
|
||||
// Guard against NaN only - ClickHouse can return numbers as strings, which
|
||||
// we should still format. Only truly non-numeric values (NaN) get passed through.
|
||||
if (isNaN(value as number)) {
|
||||
return String(value);
|
||||
}
|
||||
|
||||
if (!options) {
|
||||
return value.toString();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue