Node.js - Handle body-parser invalid JSON error
Asked Answered
B

5

24

I'm using the body-parser package like this:

// For parsing application/json:
app.use(require('body-parser').json());

// For parsing application/x-www-form-urlencoded
app.use(require('body-parser').urlencoded({ extended: true })); 

When a valid input like { "foo": "bar" } is received everything works fine and I can access the parsed object with req.body.

However, when invalid (non-JSON) data is sent:

data: JSON.stringify("just something inappropriate"),

I get this error:

{ SyntaxError: Unexpected token " in JSON at position 0
    at JSON.parse (<anonymous>)
    at createStrictSyntaxError
    at ...
expose: true,
statusCode: 400,
status: 400,
body: '"Something"',
type: 'entity.parse.failed' }

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client at ...

How can I handle this properly to prevent the server from shutting down?

Born answered 29/10, 2018 at 15:19 Comment(1)
Try reading expressjs error handling: expressjs.com/en/guide/error-handling.html, probably you need to have default error handler.Mckamey
A
41

One option is to add a custom error handler middleware and add a check to catch JSON parsing errors like that one:

app.use(require('body-parser').json()); 
app.use(require('body-parser').urlencoded({ extended: true }));

...

app.use((err, req, res, next) => {
    // This check makes sure this is a JSON parsing issue, but it might be
    // coming from any middleware, not just body-parser:

    if (err instanceof SyntaxError && err.status === 400 && 'body' in err) {
        console.error(err);
        return res.sendStatus(400); // Bad request
    }

    next();
});

Another option is to wrap body-parser's middleware to catch errors coming only from there:

const bodyParser = require('body-parser');

app.use((req, res, next) => {
    bodyParser.json()(req, res, err => {
        if (err) {
            console.error(err);
            return res.sendStatus(400); // Bad request
        }

        next();
    });
});

Or if you want to reuse this functionality to catch different errors from different middlewares, you can do:

function handleError(middleware, errorHandler) {
    middleware(req, res, err => err ? errorHandler(err, req, res, next) : next());
}

const bodyParser = require('body-parser');

app.use(handleError(bodyParser.json(), (err, req, res, next) => {
    if (err) {
        console.error(err);
        return res.sendStatus(400); // Bad request
    }

    next();
}));
Adabelle answered 29/10, 2018 at 15:39 Comment(1)
Note that the second option works with the newer express.json() as well.Kaslik
M
4

As of Express 4.16.0 - Release date: 2017-09-28 you can catch different errors from different middlewares splitting the error handler into a different function without using Bodyparser as it is deprecated.

const app = express();

function handleError(middleware, req, res, next) {
  middleware(req, res, (err) => {
    if (err) {
      console.error(err);
      return res.sendStatus(400); // Bad request
    }

    next();
  });
}

app.use((req, res, next) => {
  handleError(express.json(), req, res, next);
});

Notice in the code as of Express 4.16.0 and higher that express:

 app.use(express.json()); // Without middleware error handling.

replaces bodyParser:

 app.use(bodyParser.json()); // Without middleware error handling.
Malia answered 9/7, 2021 at 17:5 Comment(0)
A
2

There’re multiple kinds of errors raised by body-parser. They involve sending bad headers or data that are not accepted by it, or canceling requests before all the data is read.

if you want robust solutions that cover all of these errors including the one you mention use this middleware

https://www.npmjs.com/package/express-body-parser-error-handler

$ npm i express-body-parser-error-handler

and place it right after your body-parser initilization

usage example:

const bodyParserErrorHandler = require('express-body-parser-error-handler')
const { urlencoded, json } = require('body-parser')
const express = require('express')
const app = express();
router.route('/').get(function (req, res) {
    return res.json({message:"🚀"});
});

// body parser initilization
app.use(urlencoded({extended: false, limit: defaultLimitSize}));
app.use('/', json({limit: '250'}));

// body parser error handler
app.use(bodyParserErrorHandler());
app.use(router);
...
Audiophile answered 25/12, 2021 at 7:33 Comment(1)
Seems like only robust solution so farPneumatic
G
1

Add an error handler and then customize the behavior of the default way to handle that erorr, the default will be to crash as you describe.

app.use((err, req, res, callback) => {
  // todo: implement error handling logic and return an appropriate response
  console.error(err)
  res.send(500)
  callback()
})
Grandchild answered 29/10, 2018 at 15:31 Comment(0)
G
0

I maybe too late to answer this, but let me just put here. I have been receiving these errors too like:

SyntaxError: Unexpected token / in JSON at position 11

I found that when I was requesting the json like

{    
    //"name":"Tanjiro",
    "username":"tan_jiro",
    "password":"tan@jiro"
}

Only then it was giving me this error. If I request using only,

{    
    "username":"tan_jiro",
    "password":"tan@jiro"
}

It doesn't give me any error. So it looks like the error is with how the request is done rather than bodyparser.json(). Thank you.

Gooseherd answered 10/12, 2021 at 16:18 Comment(1)
Yes, because it looks like you are adding a comments for name property in JSON which is not allowed. Though JSON is inspired from Javascript object but things we can do with Javascript are all can't be done with JSON like adding a comment, putting a trailing comma etc.Jeremie

© 2022 - 2024 — McMap. All rights reserved.