Debugging & Error Handling

Node.js Fundamentals — Debugging & Error Handling
Node.js Fundamentals
Course 1 · Chapter 7 · Debugging & Error Handling

🐛 Debugging & Error Handling

Errors are inevitable in programming. This chapter teaches you to identify, handle, and debug errors effectively. We'll cover error types, try/catch patterns, logging strategies, debugging tools, and best practices for robust error handling.

📋 Error Types

JavaScript has built-in error types:

Error

Base error class. Generic errors.

TypeError

Wrong type (e.g., calling non-function).

ReferenceError

Undefined variable or function.

SyntaxError

Invalid syntax (caught at parse time).

RangeError

Value out of valid range.

Custom Errors

Create your own error classes.

📝 Console Debugging

// Basic logging console.log('Info message'); console.warn('Warning'); console.error('Error message'); // Debug levels console.debug('Debug info'); console.info('Info'); // Structured output console.table(data); console.dir(obj); // Timing console.time('myTimer'); // ... code ... console.timeEnd('myTimer'); // Assertions console.assert(value > 0, 'Value must be positive');

🎯 Try/Catch Blocks

try { // Code that might throw const result = riskyOperation(); } catch (error) { // Handle specific errors if (error instanceof TypeError) { console.error('Type error:', error.message); } else { console.error('Unknown error:', error); } } finally { // Cleanup (always runs) cleanup(); }

⚙️ Custom Error Classes

class ValidationError extends Error { constructor(message, field) { super(message); this.name = 'ValidationError'; this.field = field; } } throw new ValidationError('Invalid email', 'email');

📊 Logging Strategies

Log Levels

// DEBUG: Detailed debugging info console.debug('User ID: 123'); // INFO: General information console.log('Server started'); // WARN: Warning (recoverable) console.warn('High memory usage'); // ERROR: Error (needs attention) console.error('Database connection failed');

🔄 Async Error Handling

Promise Errors

async function loadData() { try { const data = await fetchData(); return data; } catch (error) { console.error('Failed to load:', error.message); throw error; } } // OR with .catch() fetchData() .catch(error => { console.error('Error:', error); });

📤 Error Propagation

Handle or Propagate?

Don't Swallow Errors
try { riskyOp(); } catch (e) { // Empty! Bad! }
Log or Re-throw
try { riskyOp(); } catch (e) { console.error(e); throw e; }

🔍 Stack Traces

A stack trace shows the call chain when an error occurs:

TypeError: Cannot read property 'name' of undefined at getUser (/app/users.js:5:10) at getUserName (/app/app.js:12:5) at main (/app/app.js:20:3) // Read from bottom to top (main → getUserName → getUser) // Error happened in getUser at line 5, column 10

🛠️ Debugging Tools

Node.js Debugger

$ node inspect app.js $ node --inspect app.js Then open Chrome DevTools: chrome://inspect

💻 Coding Challenges

Challenge 1: Custom Error Classes

Create custom error classes (ValidationError, DatabaseError) and use them in functions.

Goal: Learn to create and throw meaningful errors.

→ Solution

Challenge 2: Async Error Handling

Create async functions with proper try/catch and error propagation patterns.

Goal: Master async error handling in promises and async/await.

→ Solution

Challenge 3: Logging System

Build a simple logger with levels (debug, info, warn, error) and timestamps.

Goal: Understand structured logging for production apps.

→ Solution

💡 Error Handling Best Practices

1. Never swallow errors silently: Always log or re-throw.

2. Be specific: Create custom error classes for different scenarios.

3. Provide context: Include useful information in error messages.

4. Use proper status codes: 400 for bad requests, 500 for server errors.

5. Log at startup: Output config and status on app start.

🎯 What's Next

You've learned debugging and error handling! The Node.js Fundamentals course is nearly complete. We'll wrap up with Best Practices & Wrap-Up in the final chapter (node1-8).