REPL & Basic Debugging
📖 Concept
The REPL (Read-Eval-Print-Loop) is Node.js's interactive shell — a powerful tool for experimenting, debugging, and exploring APIs in real time.
Starting the REPL:
$ node # Start REPL
> 2 + 3
5
> .help # Show REPL commands
> .exit # Exit REPL
REPL special features:
_— Contains the result of the last expression- Tab completion — Press Tab to see available properties/methods
- Multi-line input — Automatically detects incomplete expressions
.load filename— Load and execute a file in the REPL.save filename— Save the REPL session to a file.editor— Enter multi-line editor mode (Ctrl+D to execute)
Debugging Node.js applications:
Method 1: console debugging (quick & dirty)
console.log, console.error, console.table, console.dir, console.trace.
Method 2: Node.js Inspector (built-in debugger)
node --inspect app.js # Start with inspector on port 9229
node --inspect-brk app.js # Break on first line
Then open chrome://inspect in Chrome or use VS Code's debugger.
Method 3: VS Code debugger (recommended)
Create .vscode/launch.json with a Node.js configuration. Set breakpoints in the editor and press F5.
Method 4: debugger statement
Place debugger; in your code — it acts as a breakpoint when running with --inspect.
The util.inspect() function:
Deeply inspect objects with control over depth, colors, and hidden properties. Unlike JSON.stringify, it handles circular references, Symbols, getters, and class instances.
Error handling basics: Node.js has two categories of errors:
- Operational errors — Expected failures (network timeout, file not found, invalid user input). Handle with try/catch, error callbacks, or rejected promises.
- Programmer errors — Bugs in code (TypeError, ReferenceError, assertion failures). Fix by correcting the code.
🏠 Real-world analogy: The REPL is like a chemistry lab — you can mix reagents (code) and immediately see the reaction (result). You wouldn't build a factory (production app) in the lab, but it's perfect for quick experiments and learning.
💻 Code Example
1// Node.js REPL and Debugging Techniques23// 1. Creating a custom REPL with pre-loaded context4const repl = require("repl");5const util = require("util");67function startCustomRepl() {8 const r = repl.start({9 prompt: "myapp > ",10 useColors: true,11 });1213 // Pre-load commonly used modules14 r.context.db = { find: (q) => `Querying: ${JSON.stringify(q)}` };15 r.context.config = { port: 3000, env: "development" };16 r.context._ = require("lodash"); // If installed1718 console.log("Custom REPL started. Pre-loaded: db, config");19}2021// Uncomment to use: startCustomRepl();2223// 2. util.inspect — Deep object inspection24const complexObj = {25 name: "Server",26 nested: {27 deep: {28 deeper: {29 value: "found it!",30 },31 },32 },33 date: new Date(),34 regex: /^hello$/gi,35 fn: function myFunc() {},36 sym: Symbol("id"),37 arr: [1, [2, [3, [4]]]],38};3940// Default depth is 2 — you miss deep values41console.log("Default inspect:", util.inspect(complexObj));4243// Full depth with colors44console.log("\nFull inspect:", util.inspect(complexObj, {45 depth: null, // Show ALL levels46 colors: true, // Syntax highlighting47 showHidden: false, // Show non-enumerable properties48 compact: false, // Pretty-print49 sorted: true, // Sort object keys50}));5152// 3. console.dir with depth control53console.dir(complexObj, { depth: null, colors: true });5455// 4. console.table for structured data56const users = [57 { name: "Alice", role: "admin", age: 30 },58 { name: "Bob", role: "user", age: 25 },59 { name: "Charlie", role: "moderator", age: 35 },60];61console.table(users);62console.table(users, ["name", "role"]); // Select columns6364// 5. console.trace — Stack trace for debugging65function a() { b(); }66function b() { c(); }67function c() {68 console.trace("How did we get here?");69}70// a(); // Uncomment to see the full call stack7172// 6. Error handling patterns73// ❌ BAD: Swallowing errors74function badErrorHandling() {75 try {76 JSON.parse("invalid json");77 } catch (e) {78 // Silent failure — impossible to debug79 }80}8182// ✅ GOOD: Handle errors meaningfully83function goodErrorHandling(jsonString) {84 try {85 return JSON.parse(jsonString);86 } catch (error) {87 console.error("Failed to parse JSON:", {88 input: jsonString.substring(0, 100),89 error: error.message,90 stack: error.stack,91 });92 throw new Error(`Invalid JSON input: ${error.message}`);93 }94}9596// 7. Custom error classes97class AppError extends Error {98 constructor(message, statusCode, isOperational = true) {99 super(message);100 this.name = this.constructor.name;101 this.statusCode = statusCode;102 this.isOperational = isOperational;103 Error.captureStackTrace(this, this.constructor);104 }105}106107class NotFoundError extends AppError {108 constructor(resource) {109 super(`${resource} not found`, 404);110 }111}112113class ValidationError extends AppError {114 constructor(field, message) {115 super(`Validation failed: ${field} - ${message}`, 400);116 this.field = field;117 }118}119120// Usage121try {122 throw new NotFoundError("User");123} catch (err) {124 console.log("\n--- Custom Error ---");125 console.log("Name:", err.name); // NotFoundError126 console.log("Message:", err.message); // User not found127 console.log("Status:", err.statusCode); // 404128 console.log("Is operational:", err.isOperational); // true129}130131// 8. Unhandled errors — last resort handlers132process.on("uncaughtException", (error) => {133 console.error("UNCAUGHT EXCEPTION:", error);134 // Log the error, then exit (don't try to recover)135 process.exit(1);136});137138process.on("unhandledRejection", (reason, promise) => {139 console.error("UNHANDLED REJECTION:", reason);140 // In production: log and exit141});
🏋️ Practice Exercise
Exercises:
- Start the Node.js REPL and explore
os,path, andcryptomodules using Tab completion - Create a custom REPL that pre-loads your project's database models and utility functions
- Use
node --inspect-brkto debug a simple script in Chrome DevTools — set breakpoints and step through - Write a custom error class hierarchy:
AppError→HttpError→NotFoundError/ForbiddenError - Create a debugging utility that wraps
console.logwith timestamps, colors, and log levels - Write a script with a deliberate bug, use
console.trace()and the debugger to find and fix it
⚠️ Common Mistakes
Using
console.log(JSON.stringify(obj))instead ofutil.inspect()— JSON.stringify crashes on circular references and hides Symbols, functions, and class infoCatching errors without doing anything (
catch (e) {}) — silent failures are the #1 source of mysterious production bugsUsing
process.on('uncaughtException')to keep the server running — after an uncaught exception, the app state is unknown; always exit and restartNot using custom error classes — throwing plain
Error('something failed')doesn't carry status codes, error types, or context needed for proper handlingRelying only on
console.logdebugging — learn the Node.js inspector for complex bugs; it shows call stacks, variables, and memory in real time
💼 Interview Questions
🎤 Mock Interview
Mock interview is powered by AI for REPL & Basic Debugging. Login to unlock this feature.