Why you get NaN in JavaScript — 3 causes and how to find where it came from

The product page shows NaN $ instead of a price. Or a café's average rating reads NaN. Or a cart total that was fine a second ago suddenly turned into three mysterious letters.
NaN means Not a Number. And here's the first oddity: in JavaScript, typeof NaN answers "number". It's a number that says it isn't a number. The second oddity is worse: NaN === NaN is false. It isn't even equal to itself.
Let's see where it comes from and how to catch it.
Why NaN is so hard to track down
NaN has a nasty property: it's contagious. Any arithmetic with it also gives NaN.
const price = NaN
price * 2 // NaN
price + 100 // NaN
Math.round(price) // NaN
So NaN surfaces far from where it was born. The mistake happened in one line, but you see it five steps later — in the grand total. No red error in the console, no crash. The program calmly keeps calculating; everything is just NaN now.
That means you're looking for the first place it appeared. Here are the three most common causes.
Cause 1. undefined got into the math (the most common)
You multiply the price by the quantity, and one of them simply isn't there.
const item = { price: 500, qty: 2 }
item.price * item.quantity // NaN — there's no quantity field, it's undefined
undefined plus a number is NaN. Most often this happens when:
- there's a typo in the field name (
quantityinstead ofqty) — the object has no such field; - the server sent a response in a different shape than the code expected;
- the data hasn't loaded yet, but the calculation has already started.
How to check. Before the suspicious line, log each part separately:
console.log("price:", item.price, "qty:", item.quantity)
Wherever you see undefined — that's the root.
How to fix. Fix the field name or supply a fallback: item.qty ?? 0. The difference between undefined and deliberate emptiness is covered in what is null.
Cause 2. Text that can't be read as a number
The value arrived as a string, and converting it failed.
Number("1 200") // NaN — a space
Number("12px") // NaN — letters
Number("3,5") // NaN — a comma
A classic with forms and spreadsheets: people write "1 200 $" and "3,5", while the code expects a clean 1200 and 3.5.
How to check. Log the value along with its type: console.log(typeof value, JSON.stringify(value)). JSON.stringify reveals the quotes and hidden spaces.
How to fix. Clean the string before converting: strip spaces, swap the comma for a dot, handle an empty string separately. The step-by-step recipe is in how to convert a string to a number.
Cause 3. Zero divided by zero
The sneakiest one, because the code looks perfect.
function average(ratings) {
const sum = ratings.reduce((a, b) => a + b, 0)
return sum / ratings.length
}
average([]) // 0 / 0 = NaN
While there are no reviews, the sum is zero and the count is zero. And 0 / 0 in JavaScript is NaN. A new café with no reviews shows a rating of "NaN".
How to check. If NaN shows up only for "new" or "empty" records, it's almost certainly division by an empty list.
How to fix. Check the length before dividing:
if (ratings.length === 0) return null // "no ratings yet"
And on screen, show an honest "No reviews yet" instead of a number.
How to check for NaN properly
Since NaN isn't equal to itself, the check if (value === NaN) will never fire. AI sometimes writes exactly that — and the check silently catches nothing.
The right way:
Number.isNaN(value) // true only for a real NaN
There's also the old isNaN(value) without Number. — but it first tries to convert the value to a number. So isNaN("hello") gives true, even though it's a string. Number.isNaN is more honest.
If you can't find the source yourself, copy the function and ask an AI: "find where NaN can appear in this calculation — check for undefined, strings and division by zero." More techniques in how to debug with AI.
Quick checklist
- Log every part of the calculation, not just the result.
- Look for
undefined— typos in field names and data that hasn't loaded. - Check the type: string or number.
- See whether you're dividing by the length of an empty list.
- Check results with
Number.isNaN, not with=== NaN.
Is NaN a bug in my code?
Not always. It's a signal that something non-numeric got into the math. JavaScript itself doesn't crash, so NaN is easy to miss — you have to catch it with a check.
Why does null + 1 give 1 while undefined + 1 gives NaN?
JavaScript converts null to zero and undefined to NaN. That's why an empty value from the database sometimes silently becomes zero. It's a separate quiet bug worth watching for too.
How do I avoid showing users "NaN $"?
Check the number before displaying it and show a clear substitute: "price on request" or a dash. Users don't need to know what NaN is.
Short story-lessons, an agent simulator and daily practice — in our mobile app. Free.





