0

Using ExpressJS 4.16.0, and NodeJS 10.15.0, and KnexJS/Bookshelf, I'm trying to figure out error handling.

Errors are being caught as expected in my application, but the error is not being returned in the response from the server call: return res.status(400).send(error);, instead I'm getting a {}.

How can I fix this?

user route:

router.post('/users/register',
  async function(req, res, next) {

    let user;

    try {
        user = await UserService.register(req.body);
    } catch (error) {
        console.log('Route: Catch: ', error); // Will display error from UserService Error here: "column users.emailll does not exist"

        return res.status(400).send(error); // Sends `{}` back
    }
    ...

UsersService:

...

try {
    user = await new User.User({
        emailll: userInput.email // Will throw error in "catch" below because "emailll" is invalid field
    }).fetch();
} catch (error) {
    // Throws error "column users.emailll does not exist"
    console.log('Service: Catch: ', error);
    throw new Error(error);
}

Response from server: {}

I'm assuming the error is being swallowed somewhere due to async await calls? Do I need to use something like this express-async-errors lib?

user3871
  • 12,432
  • 33
  • 128
  • 268

2 Answers2

2

res.send(err) will internally attempt to convert that object to JSON. By default, JSON.stringify(obj) only includes enumerable properties on the target object and the usual properties you look for on an error object are not enumerable by default.

A work-around would be to make a copy of the object with whichever properties you want to send and assigning them normally will default to enumerable:

let obj = {filename: error.filename, message: error.message};
res.send(obj);

In general, you don't want to send internal detail about your server back as an error message so usually, you would hide the implementation detail and send a message that might be more useful to the client.

So, perhaps you just want to to do:

res.status(500).send(error.message);

If you really want ALL the properties from the err object, you could also use a helper function like this:

function makeEnumerableCopy() {
    let descriptor = Object.getOwnPropertyDescriptors(err);
    // set all properties in the descriptor to be enumerable
    for (let key of Object.keys(descriptor)) {
        descriptor[key].enumerable = true;
    }
    return Object.defineProperties({}, descriptor);
}

that will make a shallow copy of the object and make all "own" properties be enumerable so you could then use it with res.send() or JSON.stringify() and get all the properties.

res.send(makeEnumerableCopy(err));
jfriend00
  • 683,504
  • 96
  • 985
  • 979
2

Try sending error message instead of error stack

return res.status(400).send(error.message);
Arif Khan
  • 100
  • 5