JavaScript Interview Prep
Error Handling

Error Types

The Six Diagnostic Codes of JavaScript

LinkedIn Hook

You wrap a block in try/catch to catch a missing semicolon. It does not work. The script never even runs. Why?

Because JavaScript has two worlds: parse time and runtime. Most SyntaxErrors happen before a single line of your code executes, which means try/catch cannot possibly catch them — the catch was never even parsed. But eval() and JSON.parse() throw SyntaxError at runtime, and those you CAN catch.

This is one of six built-in error types, each with a precise meaning. TypeError — wrong type. ReferenceError — undeclared name. RangeError — out of bounds (hello, infinite recursion). URIError — malformed % encoding. EvalError — legacy, effectively dead.

In this lesson you will learn every built-in type, what triggers each one, and exactly which ones you can catch.

Read the full lesson -> [link]

#JavaScript #InterviewPrep #ErrorHandling #JSInternals #Frontend #NodeJS #CodingInterview #WebDevelopment


Error Types thumbnail


What You'll Learn

  • The six built-in error types, what triggers each one, and when they fire
  • Why most SyntaxErrors escape try/catch — and the exact two cases where they do not
  • How every built-in type inherits from Error, and how to defend against the two most common ones

Diagnostic Codes at a Mechanic Shop

JavaScript has seven built-in error types. Think of them like diagnostic codes at a mechanic shop — each one tells you a specific category of what went wrong, which helps you fix the problem faster.

Error Types Reference Table

Error TypeWhen It OccursCatchable with try/catch?
TypeErrorOperation on wrong type (e.g., calling non-function)Yes
ReferenceErrorUsing a variable that doesn't existYes
SyntaxErrorInvalid JavaScript syntaxUsually NO (parse-time)
RangeErrorValue outside valid rangeYes
URIErrorMalformed URI encoding/decodingYes
EvalErrorIssues with eval() (legacy, rarely seen)Yes

TypeError — The Most Common One

Occurs when a value is not the expected type for an operation.

// Calling a non-function
const x = 42;
x(); // TypeError: x is not a function

// Accessing property of null/undefined
const obj = null;
obj.name; // TypeError: Cannot read properties of null

// Calling method on wrong type
const num = 123;
num.toUpperCase(); // TypeError: num.toUpperCase is not a function

// Assigning to a constant
const PI = 3.14;
PI = 3; // TypeError: Assignment to constant variable

// Calling constructor without new
function Person(name) {
  "use strict";
  this.name = name;
}
Person("Rakibul"); // TypeError in strict mode
// How to defend against TypeError
function safePropAccess(obj, prop) {
  // Optional chaining (ES2020)
  return obj?.prop;
}

// Nullish coalescing for defaults
const name = user?.name ?? "Anonymous";

ReferenceError — Using Undeclared Variables

Occurs when you try to use a variable that hasn't been declared in the accessible scope.

// Variable doesn't exist
console.log(myVar); // ReferenceError: myVar is not defined

// Accessing before declaration (TDZ — Temporal Dead Zone)
console.log(x); // ReferenceError: Cannot access 'x' before initialization
let x = 10;

// Typo in variable name
const userName = "Rakibul";
console.log(usrName); // ReferenceError: usrName is not defined
// How to safely check if something exists
if (typeof someVar !== "undefined") {
  // Safe to use someVar
}

// typeof never throws ReferenceError
console.log(typeof nonExistent); // "undefined" — no error!

SyntaxError — Usually NOT Catchable

SyntaxError typically occurs at parse time, before any code executes. This means try/catch can't catch it — the code never gets to run.

// PARSE-TIME — Cannot be caught
// This entire script will fail to load:
// const x = ; // SyntaxError: Unexpected token ';'

// The try/catch below NEVER EXECUTES because the file
// fails to parse before any code runs:
try {
  const x = ;  // SyntaxError at parse time — try/catch can't help
} catch (e) {
  // This catch NEVER runs
}
// RUNTIME SyntaxError — CAN be caught
// eval() and JSON.parse() throw SyntaxError at runtime
try {
  eval("const x = ;"); // SyntaxError thrown at RUNTIME
} catch (e) {
  console.log(e.name);    // "SyntaxError"
  console.log(e.message); // "Unexpected token ';'"
  // This catch DOES run because eval parses at runtime
}

try {
  JSON.parse("{ invalid }");
} catch (e) {
  console.log(e.name); // "SyntaxError"
  // Runtime SyntaxError from JSON.parse — catchable!
}

RangeError — Value Out of Bounds

Occurs when a value is outside the allowed range.

// Invalid array length
const arr = new Array(-1); // RangeError: Invalid array length

// Maximum call stack exceeded (infinite recursion)
function forever() {
  forever();
}
forever(); // RangeError: Maximum call stack size exceeded

// Number methods with invalid precision
const num = 1.5;
num.toFixed(200); // RangeError: toFixed() digits argument must be between 0 and 100

// Invalid date
const date = new Date("not-a-date");
date.toISOString(); // RangeError: Invalid time value

URIError — Malformed URI

Occurs when URI encoding/decoding functions receive malformed input.

// Invalid URI decoding
try {
  decodeURIComponent("%"); // URIError: URI malformed
} catch (e) {
  console.log(e.name); // "URIError"
}

try {
  decodeURI("%E0%A4%A"); // URIError: URI malformed
} catch (e) {
  console.log(e.message); // "URI malformed"
}

// Valid URI operations — no error
encodeURIComponent("hello world"); // "hello%20world"
decodeURIComponent("hello%20world"); // "hello world"

EvalError — Legacy, Rarely Seen

EvalError exists for historical reasons. Modern JavaScript engines don't throw it, but it's still available as a constructor.

// EvalError is never thrown by modern engines
// It exists for backward compatibility
const e = new EvalError("legacy error");
console.log(e instanceof EvalError); // true
console.log(e instanceof Error);     // true

// What modern engines throw instead:
// eval("invalid code") throws SyntaxError, not EvalError

All Error Types Inherit from Error

// Every built-in error is an instance of Error
const errors = [
  new TypeError("type"),
  new ReferenceError("ref"),
  new SyntaxError("syntax"),
  new RangeError("range"),
  new URIError("uri"),
  new EvalError("eval"),
];

errors.forEach((e) => {
  console.log(e.name, "instanceof Error:", e instanceof Error); // all true
});

Error Types visual 1


Common Mistakes

  • Trying to catch a missing bracket or bad syntax with try/catch in the same file — parse-time SyntaxError kills the file before try/catch is even parsed. You only catch runtime SyntaxError (from eval, new Function, JSON.parse).
  • Using if (someVar) to check whether a variable is declared — that itself throws ReferenceError. Use typeof someVar !== "undefined", which never throws.
  • Treating TypeError: Cannot read properties of undefined as "a null bug" — optional chaining (?.) + nullish coalescing (??) is almost always the right fix, and strict type checks or schema validation at the boundary prevents it from reaching deep code.

Interview Questions

Q: Name all 6 built-in JavaScript error types.

TypeError, ReferenceError, SyntaxError, RangeError, URIError, and EvalError. All six inherit from Error. EvalError is legacy — modern engines no longer throw it, but the constructor is kept for backward compatibility.

Q: Why can't you catch most SyntaxErrors with try/catch?

Most SyntaxErrors occur at parse time, before any code executes. The JavaScript engine must parse the entire file before running it. If parsing fails, no code runs — including the try/catch wrapper. However, runtime SyntaxErrors from eval(), new Function(), or JSON.parse() CAN be caught because they parse code dynamically at runtime.

Q: When CAN a SyntaxError be caught?

Whenever the syntax error happens at runtime rather than at file parse time. The three common triggers are eval(code), new Function(code), and JSON.parse(text) — each one parses a string at runtime, so if the string is invalid you get a catchable SyntaxError.

Q: What's the difference between TypeError and ReferenceError?

ReferenceError means the variable doesn't exist in scope at all — the engine can't find it. TypeError means the variable exists but you're trying to do something invalid with its value — like calling null.method() or using a number as a function.

Q: What causes RangeError: Maximum call stack size exceeded?

Infinite recursion — a function that calls itself without a proper base case. Each function call adds a frame to the call stack, and when the stack overflows, JavaScript throws this RangeError. Fix it by ensuring your recursive function has a reachable base case.


Quick Reference — Cheat Sheet

ERROR TYPES — QUICK MAP

TypeError       -> wrong type operation  (null.prop, x(), const PI=...; PI=3)
ReferenceError  -> undeclared name       (missing var, TDZ, typo)
SyntaxError     -> invalid syntax        (parse-time = UNCATCHABLE)
                                         (eval / JSON.parse = catchable)
RangeError      -> value out of bounds   (new Array(-1), infinite recursion,
                                          toFixed(>100), Invalid Date)
URIError        -> malformed URI         (decodeURIComponent('%'))
EvalError       -> legacy                (modern engines don't throw this)

All inherit from Error:
  e instanceof Error -> true   (for every built-in type)

Defenses:
  TypeError       -> obj?.prop, value ?? default, schema-validate inputs
  ReferenceError  -> typeof someVar !== "undefined" (never throws)
  SyntaxError     -> try/catch around JSON.parse / eval / new Function

Previous: Custom Errors Next: Error Handling in Promises


This is Lesson 10.3 of the JavaScript Interview Prep Course — 14 chapters, 87 lessons.

On this page