SKU // 108

JavaScript Silent Errors

A silent error is a mistake that does not throw anything. The program keeps running, but with wrong data, and you may not notice until much later. The reason is history: the first version of JavaScript (1995) had no try...catch (it arrived in 1999), so the language was designed to keep going rather than stop. Knowing where silent errors hide is half of debugging.

// Math That Does Not Complain

Impossible math gives a special number instead of an error:

console.log(1 / 0, -1 / 0);
console.log(parseInt("abc"), "abc" * 5);
console.log(Math.max());           // no arguments at all
Infinity -Infinity NaN NaN -Infinity

Infinity and NaN then spread through every calculation that uses them (JS NaN). Check with Number.isFinite(x) before trusting a result.

// = Instead of ===

A single = inside an if assigns instead of comparing. The assignment gives back the new value, so the condition is truthy and the block always runs:

let result = "Not Active.";
let isActive = false;

if (isActive = true) {       // assignment, not comparison
  result = "Active!";
}

console.log(result, isActive);
Active! true

Two bugs in one: the block ran when it should not have, and isActive itself was changed to true. JavaScript cannot flag this, because assigning inside a condition is legal (and occasionally intended).

W3Schools error
W3Schools' version of this example writes let result = "Active!"; inside the if block. That let creates a new block-scoped variable, so the outer result stays "Not Active." and the example hides the very bug it is meant to show. A silent bug inside a silent-error example.

// Missing Things Are Just undefined

Reading a property that does not exist, an array position past the end, or the result of a function that forgot to return all give undefined, with no error:

const user = { name: "Ava" };
console.log(user.nmae);                 // typo in the property name

const scores = [90, 85];
console.log(scores[2]);                 // only positions 0 and 1 exist

function double(n) { n * 2; }           // forgot return
console.log(double(4));
undefined undefined undefined

The error usually shows up later and somewhere else, when you try to use that undefined: user.nmae.length is a TypeError, far from the typo that caused it.

// Assignments That Do Nothing

Some assignments are silently ignored: setting a property on a primitive, or changing an object that was frozen with Object.freeze:

let word = "cat";
word.color = "orange";
console.log(word.color);

const settings = Object.freeze({ volume: 5 });
settings.volume = 11;
console.log(settings.volume);
undefined 5

Strict mode (JS Strict Mode) turns these into real errors, which is one of the best reasons to use it:

"use strict";
const settings = Object.freeze({ volume: 5 });
settings.volume = 11;
TypeError: Cannot assign to read only property 'volume' of object '#<Object>'

// Dates That Roll Over

An impossible date does not fail. JavaScript rolls the extra days into the next month (JS Date Set), and text it cannot read becomes an "Invalid Date" object:

const d = new Date(2026, 1, 30);        // February 30th
console.log(d.getMonth() + 1, d.getDate());

console.log(String(new Date("2026-13-45")));
3 2 Invalid Date

// Coercion That Guesses

JS Type Coercion is full of silent errors: "5" + 2 is "52", [10, 9, 1].sort() sorts as text, and == treats 0, "", and false as equal. None of them throw.

// Making Silent Errors Loud

You cannot make JavaScript complain about everything, but you can catch most silent errors early:

"use strict"Failed assignments and undeclared variables throw
=== and !==No surprise conversions in comparisons
Number.isFinite / Number.isNaNStop NaN and Infinity at the source
Check for undefinedCatch typos and missing data before using them
throw your own errorsTurn "impossible" data into a loud failure

The last row is the most powerful. When a function receives data that would silently produce garbage, throw an error instead (JS Error Statements covers throw in full):

function average(list) {
  if (list.length === 0) {
    throw new RangeError("Cannot average an empty list");
  }
  let sum = 0;
  for (const n of list) sum += n;
  return sum / list.length;
}

console.log(average([90, 80]));
console.log(average([]));
85 RangeError: Cannot average an empty list

Now the mistake stops the program right where it happened, with a message that says what went wrong, instead of an average of NaN quietly showing up on a report card.

// Quick Check

What does this log?

let count = 0;
if (count = 5) console.log("five!");
console.log(count);
Show answer
five! then 5. The single = assigns 5, which is truthy, so the if runs, and count has been changed.

Which of these does not throw an error?

  1. null.x
  2. undeclaredVariable
  3. 1 / 0
  4. (5)()
Show answer
C. It silently gives Infinity. A is a TypeError, B a ReferenceError, and D a TypeError (5 is not a function).

Why does JavaScript prefer to keep running with a wrong value instead of stopping with an error?

Show answer
History: the first version of JavaScript had no try...catch, so a thrown error could not be handled and would simply break the page. The language was designed to keep going, and those rules cannot change without breaking old websites.

// Try It

  1. Click Open Playground. Write three lines that each produce a silent NaN, Infinity, or undefined
  2. Recreate the isActive = true bug, then fix it with ===
  3. Freeze an object, try to change it with and without "use strict", and compare
  4. Add a throw to a function of your own so bad input fails loudly
// Video Walkthroughs
Last updated: Oct 10, 2026, 1:50 AM ET