JavaScript Error Reference
All JavaScript error types — TypeError, ReferenceError, SyntaxError, RangeError, and more — with causes, fixes, and handling patterns
Browse by Error Type
Your production error tracker shows TypeError: Cannot read properties of undefined (reading 'map') — 500 occurrences this week. Is it a missing API response? A race condition? An optional field? The error message tells you what failed but not why. You need to understand the error type hierarchy, common causes for each type, and the fix patterns — not just the stack trace.
Why This Reference (Not the Error Types Guide)
PureDevTools has two JavaScript error tools. This one is a comprehensive reference with every error type, common error messages, their causes, and fixes — searchable by error message text. The Error Types guide focuses on the type hierarchy and handling patterns. Use this reference when you have a specific error message to diagnose.
What Is a JavaScript Error?
A JavaScript error is an object that describes an exceptional condition — something that went wrong during parsing or execution. When an error is thrown and not caught, execution halts and the error propagates up the call stack. All built-in JavaScript errors are instances of the Error class or one of its subtypes.
Every error object has two key properties:
message— a human-readable description of the problemname— the error type name ("TypeError","RangeError", etc.)stack— a multi-line string showing the call stack at the time the error was thrown (non-standard but supported everywhere)
try {
null.foo;
} catch (e) {
console.log(e.name); // "TypeError"
console.log(e.message); // "Cannot read properties of null (reading 'foo')"
console.log(e instanceof TypeError); // true
console.log(e instanceof Error); // true
}
Standard JavaScript Error Types
TypeError
TypeError is the most common runtime error. It occurs when an operation receives a value of the wrong type — most frequently accessing a property on null or undefined, or calling a non-function.
// Accessing property on undefined:
const user = undefined;
user.name; // TypeError: Cannot read properties of undefined (reading 'name')
// Calling a non-function:
const x = 42;
x(); // TypeError: x is not a function
// Safe access with optional chaining:
const name = user?.name ?? "Anonymous"; // No error
ReferenceError
ReferenceError occurs when you reference an identifier that has never been declared in scope, or when you access a let/const variable before its initialization (the Temporal Dead Zone).
console.log(foo); // ReferenceError: foo is not defined
console.log(count); // ReferenceError: Cannot access 'count' before initialization
let count = 0;
// var is different — it is hoisted and initialized to undefined:
console.log(x); // undefined (no error)
var x = 5;
SyntaxError
SyntaxError is thrown when JavaScript cannot parse the code. At the script level, it halts the entire script before a single line runs. At runtime, it appears when JSON.parse() receives malformed input.
// Invalid JSON (most common runtime case):
JSON.parse("{ name: 'Alice' }");
// SyntaxError: Expected property name or '}' in JSON at position 2
// Correct JSON requires double quotes:
JSON.parse('{ "name": "Alice" }'); // OK
// Always wrap JSON.parse in try/catch:
try {
const data = JSON.parse(rawString);
} catch (e) {
console.error("Invalid JSON:", e.message);
}
RangeError
RangeError is thrown when a numeric value falls outside its allowed range. The most dramatic case is stack overflow from unbounded recursion.
// Infinite recursion:
function recurse() { return recurse(); }
recurse(); // RangeError: Maximum call stack size exceeded
// Invalid array length:
new Array(-1); // RangeError: Invalid array length
// Number formatting out of range:
(3.14).toFixed(200); // RangeError: toFixed() digits must be 0–100
URIError
URIError is thrown by URI encoding/decoding functions when they receive a malformed string. Most commonly encountered when decodeURIComponent() receives an invalid percent-encoding.
decodeURIComponent("%"); // URIError: URI malformed
decodeURIComponent("%GG"); // URIError: URI malformed
// Always wrap in try/catch for user-supplied URLs:
try {
const decoded = decodeURIComponent(userInput);
} catch (e) {
if (e instanceof URIError) {
console.error("Invalid URL encoding");
}
}
EvalError
EvalError is a historical error type that modern JavaScript engines no longer throw. It was originally thrown for misuse of eval(). Today, eval() misuse results in TypeError or SyntaxError. EvalError is preserved for backwards compatibility and can be caught in legacy codebases.
AggregateError
AggregateError groups multiple errors into one. Introduced in ES2021, it is thrown by Promise.any() when all promises reject. Access individual errors via the .errors array property.
try {
const result = await Promise.any([
fetch("/mirror-1/data"),
fetch("/mirror-2/data"),
fetch("/mirror-3/data"),
]);
} catch (e) {
if (e instanceof AggregateError) {
console.log("All mirrors failed:");
e.errors.forEach(err => console.error("-", err.message));
}
}
InternalError
InternalError is a non-standard Firefox-only error indicating an internal engine limit was hit — usually too much recursion. Not available in Chrome, Node.js, or Safari. In other engines, the equivalent is RangeError: Maximum call stack size exceeded.
Error Handling Best Practices
Always Specify the Error Type in catch
Catch and re-throw: handle only the errors you expect, and re-throw the rest. This prevents accidentally swallowing unexpected errors.
function parseUserConfig(raw) {
try {
return JSON.parse(raw);
} catch (e) {
if (e instanceof SyntaxError) {
throw new Error(`Invalid config format: ${e.message}`);
}
throw e; // Re-throw unexpected errors
}
}
Use the Error Cause Chain (ES2022)
The cause option links errors together, preserving the original error while adding context.
async function loadUser(id) {
try {
const res = await fetch(`/api/users/${id}`);
return await res.json();
} catch (e) {
throw new Error(`Failed to load user ${id}`, { cause: e });
}
}
// Access the original error:
try {
await loadUser(42);
} catch (e) {
console.error(e.message); // "Failed to load user 42"
console.error(e.cause.message); // Original network/parse error
}
Create Custom Error Classes
Use custom error classes to add structured context and enable precise instanceof checks.
class ValidationError extends Error {
constructor(message, field) {
super(message);
this.name = "ValidationError";
this.field = field;
}
}
function validateEmail(email) {
if (!email.includes("@")) {
throw new ValidationError("Invalid email address", "email");
}
}
try {
validateEmail("not-an-email");
} catch (e) {
if (e instanceof ValidationError) {
highlightField(e.field);
showError(e.message);
}
}
Handle Unhandled Promise Rejections
Async errors that are not caught with try/catch or .catch() become unhandled rejections. Set up a global handler to catch them:
// Browser:
window.addEventListener("unhandledrejection", (event) => {
console.error("Unhandled rejection:", event.reason);
event.preventDefault(); // Suppress console warning if handled
});
// Node.js:
process.on("unhandledRejection", (reason) => {
console.error("Unhandled rejection:", reason);
process.exit(1);
});
Frequently Asked Questions
What is the difference between TypeError and ReferenceError?
A ReferenceError means the identifier does not exist at all — the variable was never declared. A TypeError means the identifier exists but the value it holds is of the wrong type for the operation you are performing. For example: foo() throws ReferenceError if foo was never declared, but TypeError if foo is declared but holds a string instead of a function.
Why does accessing a property on undefined throw TypeError but on an undeclared variable throw ReferenceError?
undefined is a value — the variable exists and holds undefined. Accessing .property on a value of type undefined is a type mismatch, hence TypeError. An undeclared variable does not exist in the scope chain at all, so looking it up throws ReferenceError.
What is the Temporal Dead Zone (TDZ)?
The TDZ is the period between the start of a block scope and the point where a let or const variable is initialized. During this period, the variable exists (it is hoisted) but accessing it throws ReferenceError: Cannot access 'x' before initialization. var declarations do not have a TDZ — they are hoisted and initialized to undefined.
How do I safely catch errors without knowing the type?
Use instanceof to check for specific types before accessing type-specific properties. For completely unknown errors (anything could be thrown, including non-Error objects), check with instanceof Error first:
catch (e) {
if (e instanceof TypeError) { /* ... */ }
else if (e instanceof RangeError) { /* ... */ }
else if (e instanceof Error) {
// Generic error handling
console.error(e.message);
} else {
// Someone threw a non-Error (string, number, etc.)
console.error("Unknown error:", e);
}
}
How do I log the full stack trace of an error?
Use console.error(err) which automatically formats the stack, or console.error(err.stack) for the raw string. In production, send err.stack to your error tracking service alongside err.message and err.name.
Is my data private?
Yes. All processing happens entirely in your browser. No content is sent to any server.