Introduction
Debugging is an essential Node.js skill because real applications rarely work perfectly on the first attempt. Developers use debugging techniques to find syntax errors, runtime errors, incorrect values, API problems, asynchronous issues, and logical mistakes. In this chapter, you will solve practical Node.js debugging problems step by step. The examples begin with simple console.log() debugging and gradually introduce error stacks, breakpoints, the Node.js debugger, and asynchronous code. Node.js Debugging Practice Questions with Solutions help to understand the concepts.
Question 1: How do you find a syntax error in Node.js?
Problem
The following Node.js program produces an error. Find and fix the problem.
const name = "Rahul"
console.log("Hello " + name;
Solution
The problem is a missing closing parenthesis in:
console.log("Hello " + name;
Correct code:
const name = "Rahul";
console.log(
"Hello " + name
);
Output
Hello Rahul
Step-by-Step Explanation
The console.log() function starts with:
console.log(
Therefore, it must also end with:
);
The incorrect version has:
console.log("Hello " + name;
The corrected version is:
console.log("Hello " + name);
Question 2: How do you debug an undefined variable?
Problem
Find the error in this program:
const username = "Amit";
console.log(
userName
);
Solution
JavaScript is case-sensitive.
The variable was created as:
username
but the program tries to use:
userName
These are different variable names.
Correct code:
const username = "Amit";
console.log(
username
);
Output
Amit
Step-by-Step Debugging
When you see an error similar to:
ReferenceError: userName is not defined
check:
- Did you create the variable?
- Is the spelling correct?
- Is the capitalization correct?
- Is the variable available in the current scope?
Question 3: How do you use console.log() to find a wrong value?
Problem
The following program should calculate the total price, but the result is incorrect.
const price = 500;
const quantity = 3;
const total = price + quantity;
console.log(
"Total:",
total
);
Output
Total: 503
The expected answer is:
1500
Solution
The problem is this line:
const total = price + quantity;
The program is adding price and quantity.
We need multiplication:
const total =
price * quantity;
Correct program:
const price = 500;
const quantity = 3;
console.log(
"Price:",
price
);
console.log(
"Quantity:",
quantity
);
const total =
price * quantity;
console.log(
"Total:",
total
);
Output
Price: 500
Quantity: 3
Total: 1500
Step-by-Step Explanation
When debugging, print important values:
console.log(price);
console.log(quantity);
Then inspect the calculation.
The mistake becomes easier to identify.
Question 4: How do you debug a TypeError?
Problem
Find the problem in this code:
const user = {
name: "Priya",
age: 20
};
console.log(
user.name.toUpperCase()
);
console.log(
user.email.toUpperCase()
);
Solution
The first statement works because user.name contains a string.
The second statement fails because:
user.email
does not exist.
Its value is:
undefined
Calling:
undefined.toUpperCase()
causes a TypeError.
Correct Version
const user = {
name: "Priya",
age: 20,
email: "priya@example.com"
};
console.log(
user.name.toUpperCase()
);
console.log(
user.email.toUpperCase()
);
Output
PRIYA
PRIYA@EXAMPLE.COM
Safer Version
You can also check whether the value exists:
if (user.email) {
console.log(
user.email.toUpperCase()
);
}
Step-by-Step Debugging
When a TypeError occurs, inspect the value first:
console.log(
user.email
);
If the output is:
undefined
you have found the problem.
Question 5: How do you debug an asynchronous error?
Problem
The following program reads a file, but the error is not being handled correctly.
const fs =
require("fs/promises");
async function readFile() {
const data =
await fs.readFile(
"missing.txt",
"utf8"
);
console.log(data);
}
readFile();
Solution
The file does not exist, so readFile() rejects.
Use try...catch:
const fs =
require("fs/promises");
async function readFile() {
try {
const data =
await fs.readFile(
"missing.txt",
"utf8"
);
console.log(data);
} catch (error) {
console.error(
"File error:",
error.message
);
}
}
readFile();
Example Output
File error: ENOENT: no such file or directory, open 'missing.txt'
Step-by-Step Explanation
The asynchronous operation is:
await fs.readFile(...)
If the file cannot be opened, an error occurs.
The try block contains the operation:
try {
...
}
The catch block handles the error:
catch (error) {
...
}
Question 6: How do you debug an Express.js API returning the wrong data?
Problem
This API should return the user whose ID is requested.
const express =
require("express");
const app =
express();
const users = [
{
id: 1,
name: "Rahul"
},
{
id: 2,
name: "Priya"
}
];
app.get(
"/api/users/:id",
(req, res) => {
const user =
users.find(
user =>
user.id ===
req.params.id
);
res.json(user);
}
);
app.listen(
3000,
() => {
console.log(
"Server running."
);
}
);
Problem
Visit:
http://localhost:3000/api/users/1
but the result is:
null
Solution
The problem is a type mismatch.
req.params.id is a string:
"1"
The IDs in the array are numbers:
1
Strict comparison:
1 === "1"
is:
false
Convert the parameter to a number.
Correct Code
app.get(
"/api/users/:id",
(req, res) => {
const id =
Number(req.params.id);
console.log(
"Requested ID:",
id
);
const user =
users.find(
user =>
user.id === id
);
if (!user) {
return res.status(404).json({
message:
"User not found."
});
}
res.json(user);
}
);
Test
GET /api/users/1
Response
{
"id": 1,
"name": "Rahul"
}
Question 7: How do you debug a module import problem?
Problem
You have two files.
math.js:
function add(a, b) {
return a + b;
}
module.exports = {
add
};
app.js:
const math =
require("./math");
console.log(
math.sum(10, 20)
);
The program produces an error.
Solution
The exported function is named:
add
but the application tries to call:
math.sum()
The names must match.
Correct Code
math.js:
function add(a, b) {
return a + b;
}
module.exports = {
add
};
app.js:
const math =
require("./math");
console.log(
math.add(10, 20)
);
Output
30
Debugging Technique
Print the imported module:
console.log(
math
);
You may see:
{ add: [Function: add] }
This immediately shows that the module has an add function, not a sum function.
Question 8: How do you use the Node.js debugger?
Problem
Debug the following code and find why the final result is incorrect.
function calculateTotal(
price,
quantity
) {
const subtotal =
price * quantity;
const discount =
100;
const total =
subtotal + discount;
return total;
}
const result =
calculateTotal(
1000,
2
);
console.log(
result
);
The program returns:
2100
but the discount should reduce the price.
Solution
The problem is:
const total =
subtotal + discount;
It should be:
const total =
subtotal - discount;
Correct code:
function calculateTotal(
price,
quantity
) {
const subtotal =
price * quantity;
const discount =
100;
const total =
subtotal - discount;
return total;
}
const result =
calculateTotal(
1000,
2
);
console.log(
result
);
Output
1900
Using the Node.js Debugger
You can start Node.js with:
node inspect app.js
Node.js will start the built-in debugger.
You can also use:
node --inspect app.js
and connect a compatible debugging tool such as Chrome DevTools.
Why Breakpoints Help
A debugger allows you to pause program execution and inspect:
- Variables
- Function arguments
- Call stack
- Current execution line
- Expressions
- Program flow
Question 9: How do you debug an API that hangs because next() is missing?
Problem
The following Express middleware is causing the request to remain pending.
const express =
require("express");
const app =
express();
app.use(
(req, res, next) => {
console.log(
"Request received."
);
}
);
app.get(
"/",
(req, res) => {
res.send(
"Hello World"
);
}
);
app.listen(
3000,
() => {
console.log(
"Server running."
);
}
);
Solution
The middleware does not call:
next();
Therefore, Express does not continue to the next middleware or route.
Correct Code
app.use(
(req, res, next) => {
console.log(
"Request received."
);
next();
}
);
Complete Example
const express =
require("express");
const app =
express();
app.use(
(req, res, next) => {
console.log(
"Request received."
);
next();
}
);
app.get(
"/",
(req, res) => {
res.send(
"Hello World"
);
}
);
app.listen(
3000,
() => {
console.log(
"Server running."
);
}
);
Output
When you visit:
http://localhost:3000/
you receive:
Hello World
Step-by-Step Explanation
The request enters:
app.use(...)
The middleware prints:
Request received.
Then:
next();
passes control to the next matching handler.
The / route sends:
Hello World
Question 10: How do you debug a real-world Node.js application step by step?
Problem
A student-management API is returning unexpected results.
You need to debug the request from the moment it reaches the server until the response is sent.
Solution
Create logging at important points.
const express =
require("express");
const app =
express();
app.use(
express.json()
);
const students = [
{
id: 1,
name: "Rahul",
course: "Node.js"
},
{
id: 2,
name: "Priya",
course: "Python"
}
];
app.get(
"/api/students/:id",
(req, res) => {
console.log(
"1. Request received"
);
console.log(
"2. URL:",
req.originalUrl
);
console.log(
"3. Params:",
req.params
);
const id =
Number(req.params.id);
console.log(
"4. Converted ID:",
id
);
const student =
students.find(
item =>
item.id === id
);
console.log(
"5. Student found:",
student
);
if (!student) {
console.log(
"6. Student not found"
);
return res.status(404).json({
success: false,
message:
"Student not found."
});
}
console.log(
"6. Sending response"
);
res.json({
success: true,
student:
student
});
}
);
app.listen(
3000,
() => {
console.log(
"Server running on port 3000"
);
}
);
Test
Open:
http://localhost:3000/api/students/1
Example Terminal Output
Server running on port 3000
1. Request received
2. URL: /api/students/1
3. Params: { id: '1' }
4. Converted ID: 1
5. Student found: { id: 1, name: 'Rahul', course: 'Node.js' }
6. Sending response
What Did We Learn?
We traced the complete request:
Request
↓
Route
↓
Parameters
↓
Type Conversion
↓
Search
↓
Validation
↓
Response
If the response is incorrect, you can identify exactly where the value changed.
A Better Debugging Checklist
When a Node.js application behaves unexpectedly, check the problem in this order:
Step 1: Read the error message
Do not immediately change random code.
Look at:
Error type
Error message
File name
Line number
Stack trace
Step 2: Reproduce the problem
Find the exact request or action that causes the problem.
Step 3: Check the input
For an API, inspect:
req.params
req.query
req.body
req.headers
Step 4: Check important variables
Use:
console.log(value);
Step 5: Check data types
For example:
console.log(
typeof id
);
Step 6: Check the function flow
Confirm that functions are actually being called.
Step 7: Check asynchronous operations
Look for:
await
Promise
callback
try...catch
Step 8: Check the database or external service
If the API depends on another system, verify that system too.
Step 9: Use a debugger for difficult problems
Use breakpoints when logging is no longer enough.
Step 10: Fix the root cause
Avoid simply hiding the error.
Key Takeaways
1. Debugging is a core Node.js skill
Writing code is only part of development. Finding and fixing problems is equally important.
2. Read the error message first
Error messages often tell you:
- What happened
- Where it happened
- Which file caused it
- Which line caused it
3. Understand the stack trace
A stack trace can show the path through which the program reached the error.
4. Use console.log() strategically
Instead of printing everything, print important values:
console.log(
"User ID:",
userId
);
5. Check data types
This is especially important with Express:
req.params
req.query
Values received from URLs and query strings are generally strings.
6. JavaScript is case-sensitive
These are different:
username
userName
7. Learn common error types
Important errors include:
SyntaxError
ReferenceError
TypeError
8. Handle asynchronous errors
With async/await:
try {
// code
} catch (error) {
// handle error
}
9. Debug Express middleware carefully
Middleware must correctly pass control with:
next();
when it does not send the response itself.
10. Check module exports and imports
When a module fails, verify:
require("./module");
and:
module.exports
11. Use breakpoints for complex problems
A debugger lets you pause execution and inspect the application’s state.
12. Node.js has a built-in debugger
Useful commands include:
node inspect app.js
and:
node --inspect app.js
13. Reproduce the bug before fixing it
A bug that cannot be reproduced is much harder to investigate.
14. Debug one layer at a time
For an API, check:
Request
↓
Route
↓
Middleware
↓
Controller
↓
Business Logic
↓
Database
↓
Response
15. Do not hide errors
A try...catch block should help you handle or report the problem. Avoid silently ignoring errors.
16. Logging is useful in development and production
Production applications should use structured logging rather than relying only on random console.log() statements.
17. Keep debugging information useful
Instead of:
console.log(data);
prefer something clearer:
console.log(
"Payment response:",
data
);
18. Check external dependencies
If your Node.js application uses:
- Database
- API
- File system
- Authentication service
- Payment service
the problem may exist outside your immediate code.
19. Fix the root cause
Changing code until the error disappears is not good debugging. Understand why the problem occurred.
20. Practice debugging real projects
Good projects for debugging practice include:
- Todo API
- Student Management API
- Authentication API
- Course Management API
- File Upload API
- REST API with MongoDB
- Express.js CRUD application
FAQs
1. What is debugging in Node.js?
Debugging is the process of finding, understanding, and fixing problems in a Node.js application. It can involve syntax errors, runtime errors, incorrect values, asynchronous problems, API issues, and logical mistakes.
2. What is the easiest way to debug Node.js code?
For beginners, console.log() is one of the easiest methods.
For example:
console.log(
"User:",
user
);
As applications become more complex, use the Node.js debugger and breakpoints.
3. What is a stack trace in Node.js?
A stack trace is information that shows where an error occurred and the sequence of function calls that led to the error. It helps developers locate the source of a problem.
4. How do I debug an Express.js API?
Start by checking the request URL, HTTP method, parameters, query values, request body, middleware, controller logic, database operations, and response. Logging important values at each stage can help identify where the problem occurs.
5. Why does req.params.id sometimes cause a comparison problem?
Route parameters are received as strings. If your database or array stores IDs as numbers, this comparison can fail:
1 === "1"
Convert the value when appropriate:
const id =
Number(req.params.id);
6. How do I debug asynchronous code in Node.js?
Use try...catch with async/await, inspect promise errors, and use the debugger when necessary.
Example:
try {
const result =
await someOperation();
} catch (error) {
console.error(
error
);
}
7. Is console.log() enough for Node.js debugging?
console.log() is excellent for learning and simple problems, but it is not always enough for complex applications. The Node.js debugger, breakpoints, structured logging, tests, and monitoring tools become more useful as projects grow.
Written by Shubhranshu Shekhar, who has trained 20000+ students in coding.
