JavaScript errors can be frustrating, especially when you're not sure what's causing them. After years of debugging JavaScript applications, I've compiled the most common errors developers face and how to fix them.
1. "Cannot read property of undefined" / "Cannot read property of null"
The Error:
// TypeError: Cannot read property 'name' of undefined
const userName = user.name;Why It Happens:
You're trying to access a property on an object that doesn't exist or is undefined.
The Fix:
// Option 1: Optional chaining (ES2020)
const userName = user?.name;
// Option 2: Default value with nullish coalescing
const userName = user?.name ?? 'Guest';
// Option 3: Check before accessing
const userName = user && user.name ? user.name : 'Guest';
// Option 4: Provide default object
const userName = (user || {}).name || 'Guest';Best Practice:
// Always use optional chaining for nested properties
const city = user?.address?.city ?? 'Unknown';
// Works with arrays too
const firstItem = items?.[0];
const itemName = items?.[0]?.name;2. "TypeError: Cannot read property 'map' of undefined"
The Error:
// TypeError: Cannot read property 'map' of undefined
const items = data.map(item => item.name);Why It Happens:
You're calling map() on something that isn't an array (usually undefined or null).
The Fix:
// Option 1: Provide default empty array
const items = (data || []).map(item => item.name);
// Option 2: Check if array exists
const items = Array.isArray(data) ? data.map(item => item.name) : [];
// Option 3: Use optional chaining
const items = data?.map(item => item.name) ?? [];
// Option 4: Early return
if (!Array.isArray(data)) {
return [];
}
const items = data.map(item => item.name);3. "ReferenceError: [variable] is not defined"
The Error:
// ReferenceError: userName is not defined
console.log(userName);Why It Happens:
You're trying to use a variable that hasn't been declared or is out of scope.
The Fix:
// Declare the variable
let userName = 'John';
console.log(userName);
// Or use const/var
const userName = 'John';
var userName = 'John'; // Avoid var in modern JSCommon Scenarios:
// Scope issue
function example() {
if (true) {
let userName = 'John';
}
console.log(userName); // ReferenceError - userName is not in scope
}
// Fix: Declare outside the block
function example() {
let userName;
if (true) {
userName = 'John';
}
console.log(userName); // Works!
}4. "TypeError: [function] is not a function"
The Error:
// TypeError: data.map is not a function
const result = data.map(x => x * 2);Why It Happens:
You're calling a method on a value that doesn't have that method (e.g., calling map on an object instead of an array).
The Fix:
// Check the type first
if (Array.isArray(data)) {
const result = data.map(x => x * 2);
} else {
console.error('data is not an array');
}
// Or convert to array
const result = Array.from(data || []).map(x => x * 2);
// For objects, use Object methods
const result = Object.values(data || {}).map(x => x * 2);5. "SyntaxError: Unexpected token"
The Error:
// SyntaxError: Unexpected token
const obj = { name: 'John', age: 30, };Why It Happens:
Syntax errors occur when JavaScript can't parse your code. Common causes:
- Missing brackets, braces, or parentheses
- Trailing commas in wrong places (though trailing commas are usually OK)
- Using reserved words as variable names
The Fix:
// Check for missing brackets
const obj = { name: 'John', age: 30 }; // Remove trailing comma if causing issues
// Missing closing brace
function example() {
if (true) {
console.log('test');
} // Make sure all braces are closed
}
// Use a linter/IDE to catch syntax errors6. "RangeError: Maximum call stack size exceeded"
The Error:
// RangeError: Maximum call stack size exceeded
function infiniteLoop() {
infiniteLoop();
}
infiniteLoop();Why It Happens:
Infinite recursion or a function calling itself too many times.
The Fix:
// Add a base case to stop recursion
function countdown(n) {
if (n <= 0) {
return; // Base case - stops recursion
}
console.log(n);
countdown(n - 1); // Recursive call with different value
}
// Or use iteration instead
function countdown(n) {
for (let i = n; i > 0; i--) {
console.log(i);
}
}7. "TypeError: Cannot set property of undefined"
The Error:
// TypeError: Cannot set property 'name' of undefined
user.name = 'John';Why It Happens:
You're trying to set a property on an object that doesn't exist.
The Fix:
// Initialize the object first
let user = {};
user.name = 'John';
// Or use object initialization
const user = {
name: 'John'
};
// Or check if object exists
if (user) {
user.name = 'John';
}
// Or use optional chaining with assignment
user = user || {};
user.name = 'John';8. "Uncaught Promise Rejection"
The Error:
// Uncaught (in promise) Error: Something went wrong
fetch('/api/data')
.then(response => response.json())
.then(data => console.log(data));
// If fetch fails, promise is rejected but not caughtWhy It Happens:
A promise was rejected but you didn't handle the error with .catch() or try/catch.
The Fix:
// Option 1: Use .catch()
fetch('/api/data')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
// Option 2: Use async/await with try/catch
async function fetchData() {
try {
const response = await fetch('/api/data');
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Error:', error);
}
}
// Option 3: Handle errors in Promise.all
Promise.all([fetch('/api/1'), fetch('/api/2')])
.then(responses => Promise.all(responses.map(r => r.json())))
.catch(error => console.error('One or more requests failed:', error));9. "TypeError: Assignment to constant variable"
The Error:
// TypeError: Assignment to constant variable
const x = 5;
x = 10; // Error!Why It Happens:
You're trying to reassign a value to a const variable, which is not allowed.
The Fix:
// Use let instead of const if you need to reassign
let x = 5;
x = 10; // Works!
// For objects/arrays, you can modify properties/elements
const obj = { name: 'John' };
obj.name = 'Jane'; // Works! (modifying property)
obj.age = 30; // Works! (adding property)
// But you can't reassign the entire object
obj = { name: 'Jane' }; // Error!
const arr = [1, 2, 3];
arr.push(4); // Works! (modifying array)
arr[0] = 10; // Works! (modifying element)
arr = [1, 2, 3, 4]; // Error! (reassigning array)10. "TypeError: [object] is not iterable"
The Error:
// TypeError: user is not iterable
for (const item of user) {
console.log(item);
}Why It Happens:
You're trying to iterate over something that isn't iterable (like an object) using for...of.
The Fix:
// For objects, use Object.keys(), Object.values(), or Object.entries()
for (const key of Object.keys(user)) {
console.log(key, user[key]);
}
// Or use for...in
for (const key in user) {
console.log(key, user[key]);
}
// Or use Object.entries()
for (const [key, value] of Object.entries(user)) {
console.log(key, value);
}
// For arrays, for...of works fine
const arr = [1, 2, 3];
for (const item of arr) {
console.log(item); // Works!
}Debugging Tips
1. Use Browser DevTools:
- - Open Console (F12)
- - Check the error message and stack trace
- - Set breakpoints to inspect variables
2. Use console.log strategically:
```javascript
console.log('Variable value:', variable);
console.table(arrayOfObjects); // Better for arrays of objects
console.dir(object); // Better for objects
```
3. Use TypeScript:
- - Catches many errors at compile time
- - Provides better IDE support
4. Use a Linter:
- - ESLint catches common mistakes
- - Prettier formats code consistently
5. Read the Error Message:
- - Error messages usually tell you exactly what's wrong
- - Check the line number and file
Prevention Strategies
1. Always initialize variables
2. Use TypeScript for type safety
3. Validate data before using it
4. Use optional chaining for nested properties
5. Handle promise rejections
6. Use linters and formatters
7. Write tests to catch errors early
Conclusion
Most JavaScript errors are preventable with good practices:
- Always check if values exist before using them
- Use optional chaining and nullish coalescing
- Handle promise rejections
- Use TypeScript for type safety
- Read error messages carefully
Understanding these common errors will make you a better JavaScript developer and save you hours of debugging time.