Debugging a Node.js Express API in VSCode Debugger
Tags: express, node, api, debugging
Published: 2019-04-08 18:52:21

---
title: Debugging a Node.js Express API in VSCode Debugger
published: true
description: How to use the integrated debugger of VSCode to debug APIs build in Javascript NodeJs and Express stack.
tags: express, nodejs, api, debugging
cover_image: https://thepracticaldev.s3.amazonaws.com/i/h2kisqs8jfufrtljhymb.jpg
canonical_url: https://www.moesif.com/blog/technical/debugging/debugging-nodejs-api-with-vscode/
---

*[Cover image by Harald Deischinger on Flickr.](https://www.flickr.com/photos/deischi/)*

## Why

When we create software, we rarely do it without errors. API creation isn't exempt from this fact, so sooner or later we are in the position to debug it. In JavaScript, the first stop for a debugging task is often _logging to the console_, but using a debugger can give us a more integrated experience.

In this tutorial, we will learn _how to debug an [Express-based API](https://www.moesif.com/blog/api-guide/development/api-resources-for-nodejs-developers/) with the help of Visual Studio Code_.

## What

[Express](https://expressjs.com/) is a _"minimalist web framework for Node.js"_. It allows us to **link functions directly to API endpoints**, which is a quick and simple way to build an API.

[Visual Studio Code](https://code.visualstudio.com/) is a _"streamlined code editor with support for development operations like **debugging**, task running and version control."_

We will also use [cURL](https://curl.haxx.se/) to send requests to our API.

## How

We will create a simple API with the Express framework and then try to debug it with the help of VSCodes debugging features instead of the console.

### API Setup

First, we create a new Node.js project and install our dependencies.

```
$ mkdir api
$ cd api
$ npm init
$ npm i express body-parser
```

Next, we create an `index.js` file that will act as our main server script.

```javascript
const express = require("express");
const bodyParser = require("body-parser");

const users = [{ id: 0, name: "admin" }];

const server = express();
server.use(bodyParser.json());

server.get("/users", (_, response) => response.send({ users }));
server.get("/users/:id", ({ params: { id } }, response) => {
  const user = users[id];
  response.send({ user });
});
server.post("/users", ({ body }, response) => {
  const { user } = body;
  user.id = users.length;
  users.push(user);
  response.send({ user });
});

server.listen(9999, () =>
  console.log("API running on http://localhost:9999")
);
```

We use the `users` array as our in-memory data-store. It gets initialized with an admin user.

Next, we create our Express `server` and use the JSON middleware of the `bodyParser` package; it allows us to access the values of a JSON string stored in the body of a `POST` HTTP request.

Then, we create three API-endpoints. Two `GET` endpoints so we can request a list of all users and one specific user by its ID and one `POST` endpoint to create a new user.

Let's start the API with the following command!

```
$ node .
API running on http://localhost:9999
```

### Using the API

Now that our API is up and running we can try to query it with cURL. For this, we need to open a new terminal window and execute the following commands.

Create a user:

```
$ curl -H "Content-Type:application/json" -d '{"user":{"name": "kay"}}' localhost:9999/users
{"user":{"id":1,"name":"kay"}}
```

List all users:

```
$ curl localhost:9999/users
{"users":[{"id":0,"name":"admin"},{"id":1,"name":"kay"}]}
```

List one user:

```
$ curl localhost:9999/users/1
{"user":{"id":1,"name":"kay"}}
```

Create another user:

```
$ curl -H "Content-Type:application/json" -d '{"users":{"name": "xing"}}' localhost:9999/users
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
...
```

_Oh no!_ We have a typo in the JSON, `users` instead of `user`. Since we didn't handle this in our `POST /users` endpoint, Express just responded with an HTML formatted error.

This is a simple example of a problem that could be fixed without much hassle, but let's use it to start VSCodes debugger so we can investigate what went wrong directly at runtime.

### Using VSCodes Debugger

Debugging Node.js APIs with VSCode is very easy.

We check which endpoint we want to debug and **set a breakpoint inside the function** that endpoint triggers. This is done with a left-click left to the line number. Let's to it on _line 15_, which should be the first line of our `POST /users` endpoint function.

<img src="https://thepracticaldev.s3.amazonaws.com/i/hwea4hlx4mpuxiorl8i5.png" alt="VSCode Breakpoint Screenshot" width="500">

Then we start the debugger by clicking on _Debug->Start Debugging_ at the top menu or by pressing _F5_.

<img src="https://thepracticaldev.s3.amazonaws.com/i/xryi7bsg4mq36z7gbxpl.jpg" alt="VSCode Menu Screenshot" width="300">

VSCode will start our application and the debugger for us. It will also link the two together via Node.js' debugging protocol.

Then we re-send the request that led to an error with cURL and try to find out what happens.

```
$ curl -H "Content-Type:application/json" -d '{"users":{"name": "xing"}}' localhost:9999/users
```

This request will run the function linked to `POST /users` and halt at the break-point in its first line.

If we look at the side-bar on the left of our code, we can see a _VARIABLES_ category with various sub-categories like _Block_ and _Local_. Let's open _Local_ and see what's inside.

<img src="https://thepracticaldev.s3.amazonaws.com/i/lrme7tpuudstyedo9r79.png" alt="VSCode Sidebar Screenshot" width="300">

As we can see, we have two local variables, `body` which is of type `Object` and `response` which is of type `ServerResponse`.

Let's step to the next line with _F10_ to see what happens.

All seems to work as expected.

Let's step to the next line again.

**BOOM!**

Somehow we ended up in a whole different place of the code-base?

<img src="https://thepracticaldev.s3.amazonaws.com/i/ue0jlgrlsx4iucfs5uw5.png" alt="VSCode File Path Screenshot" width="400">

It seems like we created an error by setting the `id` of our `user` object, how did this happen?

Let's open our `index.js` again, move the break-point to _line 16_ and let the debugger run to the end of the event loop by pressing _F5_.

Then re-send the request with cURL to see what happened before we tried to set `user.id`.

When we look into the side-bar in the _VARIABLES/Block_ category, we can see that our `user` object is in fact `undefined`! If we open the _VARIABLES/Local_ category, we can also see why.

<img src="https://thepracticaldev.s3.amazonaws.com/i/20mb40i9vq8a220jqg0f.png" alt="VSCode Sidebar Screenshot" width="300">

Our `body` has a `users` attribute, but we try to destructure a `user` variable from it in _line 15_, which leads to an error when we try to write to `user.id` in _line 16_.

Now that we now our problem, let's stop the debugger and fix it.

```javascript
server.post("/users", ({ body }, response) => {
  const { user } = body;

  if (!(user instanceof Object))
    return response.send({ error: '"user" object missing in JSON!' });

  user.id = users.length;
  users.push(user);
  response.send({ user });
});
```

Let's restart our server, so it runs the new code:

```
$ node .
API running on http://localhost:9999
```

And resend our problematic request:

```
$ curl -H "Content-Type:application/json" -d '{"users":{"name": "xing"}}' localhost:9999/users
{"error":"\"user\" object missing in JSON!"}
```

Finally, we get a useful JSON formatted error message.

## Conclusion

Debugging Node.js based APIs with the help of VSCodes integrated debugger is a straight-forward task. We just need to set a break-point, no additional code involved.

It gives us many runtime insights out-of-the-box, including:

- Values of current variables
- Ability to watch single variables
- Current call-stack
- Currently loaded scripts

---

*Moesif is the most advanced API Analytics platform, supporting REST, GraphQL, Web3 Json-RPC and more. Over two thousand companies process billions of API calls through Moesif for deep insights into their platforms.* **[Learn More](https://moesif.com/features?int_source=blog)**

---

*Originally published at www.moesif.com*