javascript
JavaScript Error Handling
Error handling allows your program to gracefully handle unexpected situations instead of crashing. Learn how to catch and manage errors effectively.
Types of Errors
Syntax Errors
Code that doesn't follow JavaScript syntax rules:
javascript
// Missing closing bracket
function broken() {
console.log('Hello'
// SyntaxError: Unexpected end of input
// Invalid syntax
let 123abc = 'value';
// SyntaxError: Invalid or unexpected token
Runtime Errors
Errors that occur during execution:
javascript
// ReferenceError
console.log(nonExistentVariable);
// ReferenceError: nonExistentVariable is not defined
// TypeError
let num = 42;
num.toUpperCase();
// TypeError: num.toUpperCase is not a function
// RangeError
let arr = new Array(-1);
// RangeError: Invalid array length
Logical Errors
Code runs but produces wrong results:
javascript
// Wrong logic - no error thrown
function calculateArea(width, height) {
return width + height; // Should be width * height
}
try...catch Statement
Handle errors gracefully:
javascript
try {
// Code that might throw an error
let result = riskyOperation();
console.log(result);
} catch (error) {
// Handle the error
console.log('An error occurred:', error.message);
}
Basic Example
javascript
try {
let data = JSON.parse('invalid json');
} catch (error) {
console.log('Failed to parse JSON:', error.message);
}
// Program continues running
The Error Object
javascript
try {
throw new Error('Something went wrong!');
} catch (error) {
console.log(error.name); // 'Error'
console.log(error.message); // 'Something went wrong!'
console.log(error.stack); // Stack trace
}
finally Block
Code that runs regardless of success or failure:
javascript
try {
console.log('Trying...');
// risky code
} catch (error) {
console.log('Error:', error.message);
} finally {
console.log('This always runs');
// Cleanup code (close files, connections, etc.)
}
Practical Example
javascript
function readFile(filename) {
let file;
try {
file = openFile(filename);
return processFile(file);
} catch (error) {
console.log('Error reading file:', error.message);
return null;
} finally {
if (file) {
closeFile(file); // Always close the file
}
}
}
Throwing Errors
Create and throw your own errors:
javascript
function divide(a, b) {
if (b === 0) {
throw new Error('Cannot divide by zero');
}
return a / b;
}
try {
let result = divide(10, 0);
} catch (error) {
console.log(error.message); // 'Cannot divide by zero'
}
Error Types
JavaScript has several built-in error types:
javascript
// Error - generic error
throw new Error('Generic error');
// ReferenceError - invalid reference
throw new ReferenceError('Variable not found');
// TypeError - wrong type
throw new TypeError('Expected a number');
// RangeError - value out of range
throw new RangeError('Index out of bounds');
// SyntaxError - syntax error
throw new SyntaxError('Invalid syntax');
Custom Errors
Create your own error types:
javascript
class ValidationError extends Error {
constructor(message) {
super(message);
this.name = 'ValidationError';
}
}
function validateAge(age) {
if (age < 0) {
throw new ValidationError('Age cannot be negative');
}
if (age > 150) {
throw new ValidationError('Age seems unrealistic');
}
return true;
}
try {
validateAge(-5);
} catch (error) {
if (error instanceof ValidationError) {
console.log('Validation failed:', error.message);
} else {
throw error; // Re-throw if not our error
}
}
Handling Specific Errors
javascript
try {
// Some code
performOperation();
} catch (error) {
if (error instanceof TypeError) {
console.log('Type error:', error.message);
} else if (error instanceof ReferenceError) {
console.log('Reference error:', error.message);
} else {
console.log('Unknown error:', error.message);
}
}
Async Error Handling
With Promises
javascript
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.log('Fetch error:', error.message));
With async/await
javascript
async function fetchData() {
try {
let response = await fetch('https://api.example.com/data');
let data = await response.json();
console.log(data);
} catch (error) {
console.log('Error fetching data:', error.message);
}
}
Complete Example
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Error Handling Demo</title>
<style>
body {
font-family: Arial, sans-serif;
padding: 20px;
max-width: 800px;
margin: 0 auto;
}
.demo {
background: #f5f5f5;
padding: 15px;
margin: 15px 0;
border-radius: 5px;
}
button {
background: #3498db;
color: white;
border: none;
padding: 10px 20px;
margin: 5px;
cursor: pointer;
border-radius: 4px;
}
button:hover {
background: #2980b9;
}
.output {
background: white;
padding: 10px;
margin-top: 10px;
border-radius: 3px;
}
.error {
color: #e74c3c;
background: #fadbd8;
padding: 10px;
border-radius: 3px;
margin: 5px 0;
}
.success {
color: #27ae60;
background: #d5f4e6;
padding: 10px;
border-radius: 3px;
margin: 5px 0;
}
input {
padding: 8px;
margin: 5px;
border: 2px solid #ddd;
border-radius: 4px;
}
</style>
</head>
<body>
<h1>JavaScript Error Handling</h1>
<div class="demo">
<h2>Basic try...catch</h2>
<button onclick="basicTryCatch()">Run Demo</button>
<div id="basic-output" class="output"></div>
</div>
<div class="demo">
<h2>Division Calculator</h2>
<input type="number" id="num1" placeholder="Number 1" value="10">
<input type="number" id="num2" placeholder="Number 2" value="2">
<button onclick="calculateDivision()">Divide</button>
<div id="calc-output" class="output"></div>
</div>
<div class="demo">
<h2>JSON Parser</h2>
<input type="text" id="json-input" placeholder='Enter JSON' value='{"name":"John"}' style="width: 300px;">
<button onclick="parseJSON()">Parse</button>
<div id="json-output" class="output"></div>
</div>
<div class="demo">
<h2>Age Validator</h2>
<input type="number" id="age-input" placeholder="Enter age" value="25">
<button onclick="validateAge()">Validate</button>
<div id="age-output" class="output"></div>
</div>
<div class="demo">
<h2>finally Block Demo</h2>
<button onclick="finallyDemo()">Run Demo</button>
<div id="finally-output" class="output"></div>
</div>
<script>
function basicTryCatch() {
let output = '';
// Example 1: Successful execution
try {
output += '<div class="success">✓ Successful operation</div>';
let result = 10 + 20;
output += `Result: ${result}<br>`;
} catch (error) {
output += `<div class="error">Error: ${error.message}</div>`;
}
// Example 2: Error caught
try {
output += '<br>Attempting to access undefined variable...<br>';
console.log(undefinedVariable);
} catch (error) {
output += `<div class="error">✗ ${error.name}: ${error.message}</div>`;
}
output += '<div class="success">Program continues running!</div>';
document.getElementById('basic-output').innerHTML = output;
}
function calculateDivision() {
let num1 = parseFloat(document.getElementById('num1').value);
let num2 = parseFloat(document.getElementById('num2').value);
let output = '';
try {
if (isNaN(num1) || isNaN(num2)) {
throw new Error('Please enter valid numbers');
}
if (num2 === 0) {
throw new Error('Cannot divide by zero');
}
let result = num1 / num2;
output = `<div class="success">✓ ${num1} ÷ ${num2} = ${result}</div>`;
} catch (error) {
output = `<div class="error">✗ ${error.message}</div>`;
}
document.getElementById('calc-output').innerHTML = output;
}
function parseJSON() {
let input = document.getElementById('json-input').value;
let output = '';
try {
let parsed = JSON.parse(input);
output = `<div class="success">✓ Valid JSON</div>`;
output += `<pre>${JSON.stringify(parsed, null, 2)}</pre>`;
} catch (error) {
output = `<div class="error">✗ Invalid JSON: ${error.message}</div>`;
}
document.getElementById('json-output').innerHTML = output;
}
// Custom error class
class ValidationError extends Error {
constructor(message) {
super(message);
this.name = 'ValidationError';
}
}
function validateAge() {
let age = parseInt(document.getElementById('age-input').value);
let output = '';
try {
if (isNaN(age)) {
throw new ValidationError('Please enter a valid number');
}
if (age < 0) {
throw new ValidationError('Age cannot be negative');
}
if (age > 150) {
throw new ValidationError('Age seems unrealistic');
}
if (age < 18) {
output = `<div class="success">✓ Valid age: ${age} (Minor)</div>`;
} else {
output = `<div class="success">✓ Valid age: ${age} (Adult)</div>`;
}
} catch (error) {
if (error instanceof ValidationError) {
output = `<div class="error">✗ ${error.message}</div>`;
} else {
output = `<div class="error">✗ Unexpected error: ${error.message}</div>`;
}
}
document.getElementById('age-output').innerHTML = output;
}
function finallyDemo() {
let output = '';
let steps = [];
try {
steps.push('1. Entering try block');
steps.push('2. Performing operation');
let result = 10 / 2;
steps.push(`3. Result: ${result}`);
} catch (error) {
steps.push(`Error: ${error.message}`);
} finally {
steps.push('4. Finally block always executes');
steps.push('5. Cleanup operations here');
}
steps.push('6. Program continues');
output = steps.map(step => `<div>${step}</div>`).join('');
document.getElementById('finally-output').innerHTML = output;
}
</script>
</body>
</html>
Preview
Best Practices
- Use try...catch for expected errors - Don't catch everything
- Be specific with error handling - Handle different error types differently
- Always use finally for cleanup - Close files, connections, etc.
- Throw meaningful errors - Include helpful error messages
- Don't catch and ignore - At least log the error
- Use custom errors - Create specific error types for your app
- Validate input early - Prevent errors before they happen
Common Patterns
Input Validation
javascript
function processUserInput(input) {
try {
if (!input) {
throw new Error('Input is required');
}
if (typeof input !== 'string') {
throw new TypeError('Input must be a string');
}
// Process input
return input.toUpperCase();
} catch (error) {
console.error('Validation error:', error.message);
return null;
}
}
API Calls
javascript
async function fetchUserData(userId) {
try {
const response = await fetch(`/api/users/${userId}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('Failed to fetch user:', error.message);
return null;
}
}