Blank numeric fields parse to NaN not zero
-
What you'll see
A total comes out wrong. Not visibly broken — just lower than it should be, or
NaNin one cell of an otherwise correct table. It reproduces only for records where one numeric field was left blank, and every guard in the code looks right:let q = parseInt(row.Quantity); // "" -> NaN let sum = q * row.Price; // NaN return sum; // NaN reaches the pageCode written against an older engine is the common source. Docly's numeric parsing has not always matched the spec, so a workspace can contain parse sites that were correct when they were written and are a source of
NaNnow. -
What's actually happening
parseInt("")andparseFloat("")returnNaN, per the ECMAScript specification. So doesparseInt(null). Once aNaNenters a calculation it propagates through every subsequent operation —NaN * 2,NaN + 10andNaN / 3are allNaN— so the failure surfaces a long way from the field that caused it.Number()is not a drop-in alternative, because it disagrees in both directions:Input parseFloatNumber""NaN0nullNaN0"83 %"83NaN"12.5"12.512.5That difference decides which one belongs where. A rendered table cell holds a formatted value like
"83 %", whichparseFloatreads as83andNumberturns intoNaN. A stored numeric field holds either a clean number or nothing, andNumber("")is already0, so on the serverNumberneeds anisNaNguard only to catch genuine garbage. -
What to do
1. Guard at the parse site, not at the readout. This restores the intent the code was written with, rather than inventing a policy further down:
let q = parseInt(row.Quantity); if (isNaN(q)) q = 0;2. A falsy check hides the problem rather than handling it.
if (!sum) sum = 0;andsum || 0are the usual reflexes, and both do catchNaN— which is exactly what makes them the wrong tool. The guard fires, the corrupted total is replaced with a plausible one, and the blank field that caused it leaves no trace. A wrong number hides far better than a visibleNaN. Test for the condition you actually mean, withisNaN(), at the point where the value enters the calculation.3. Pick the function by side.
Where Use Why Client-side, reading rendered cells parseFloatA cell holds "83 %";NumbergivesNaNServer-side, reading stored fields NumberNumber("")andNumber(null)are already04. When a total is wrong rather than missing, suspect a blank field before you suspect the arithmetic. A single un-guarded parse poisons every figure downstream of it, so the symptom appears in the summary row while the cause sits in one record.
5. Check the behaviour rather than assuming it if you are working in a codebase old enough to predate the current engine. A throwaway page settles it in one request — see Use a scratch hash file to test Docly functions.
Last reviewed 21 Aug 2026