VIVEK JAIN
VIVEK JAIN

Reputation: 116

How to Throw custom Errors?

I am trying to use passport-jwt strategy for authentication.

Here is my code :-

router.post('/register', async (req, res) => {
    const { username, email } = req.body;
    try {
        const user = await User.findOne({ username });
        if (user) {
            throw new Error('User with same username already exists !!');
        }
        const newUser = new User({
            username,
            email
        })
        const salt = await bcrypt.genSalt(10);
        newUser.password = await bcrypt.hash(req.body.password, salt);
        const savedUser = await newUser.save();
        res.json({
            status: 200,
            'Content-Type': 'Application/Json',
            'message': `You have successfully regirstered yourself, ${savedUser.username}!`
        })
    } catch (err) {
        err.statusCode = 500;
        console.log(err.message);
        res.header({
            status: '200',
            'Content-Type': 'Application/Json',
        });
        res.json(err);
    }
});

Now this route is working just fine, it's doing all the things till now. The only problem is, When i find an existing user, I want to throw a new error with a custom message. Javascript has this Error class which I can use to throw these errors.

The problem occurs when it catches error. When I console.log(err.message), I can see my custom message perfectly. But the err object that I am returning in response via res.json(err) does not have any message but only statusCode.

I want to know why this is happening and what's the solution for this ? Right now, I am doing this by doing something like this :-

res.json({
    statusCode: 500,
    message : err.message
});

But I would like to return the err object with both statusCode and message fields populated.

Upvotes: 3

Views: 4419

Answers (4)

Krzysztof Kaczyński
Krzysztof Kaczyński

Reputation: 5071

You can create your own Error class which can take more than one parameter in the constructor. This class has to extend base Error JavaScript class. For example:

class MyCustomError extends Error {
  constructor(msg, statusCode) {
    super(msg);
    this.statusCode = statusCode;
    this.name = MyCustomError.name;
  }
}

function throwCustomError() {
  throw new MyCustomError('Some custom message', 404);
}

try {
  throwCustomError();
} catch (error) {
  console.log(error.message);
  console.log(error.statusCode);
  console.dir(error);
}

Remember that you have to call super on the beginning of the constructor if you are extending another class

Upvotes: 9

Aryan Gupta
Aryan Gupta

Reputation: 26

You are passing the error object to the json method of the response object. But this only takes JSON parseable string as a parameter. What you can do is use -

res.json(JSON.stringify(err))

and at the place where you are using this response, you need to parse this string as JSON and then convert it into an Error object. You can use the following syntax assuming your front-end also uses javascript

err = new Error(JSON.parse(response.data))

Upvotes: 1

bel3atar
bel3atar

Reputation: 943

From the documentation of res.json() : This method sends a response (with the correct content-type) that is the parameter converted to a JSON string using JSON.stringify(). Now running JSON.stringify(new Error('custom msg')) we get "{}"

Upvotes: 0

zx01
zx01

Reputation: 571

Replace the entire catch block with the following line of code.

res.status(500).json({
   message: err.message
})

Upvotes: 0

Related Questions