0

I am creating a NodeJS API using Express, PostgreSQL in which I created a controller function which will check the user from the database.

const checkUser = async (req, res) => {
  try {
    const user = await pool.query('select * from users where email = $1', [req.body.email]);

    if (user.rows.length === 0) throw new Error('Error Found');

    return res.json("User Found");
  } catch (e) {

//=======   Output at console ========
//Error: Error Found 

    console.log(e); 

//========  Response Object Received From API ==========
// {
//   "msg": "Error Found",
//   "Error": {}
// }

    res.status(400).send({ msg: 'Error Found', Error: e });

  }
};

Consider the situation that the user is not found in the Database so from try block the control passes to the catch block.

1- I am not able to get why the Error thrown from the try block to catch block sends back an empty object as a response. Also, at the same time using console.log prints the correct output value in the console.
2- I want a fix so that I can send e as a response to the User.

Kevin Martin
  • 39
  • 1
  • 9
  • 1
    What you see is a side-effect of how JSON.stringify treats Errors, answered well in [this thread](https://stackoverflow.com/a/50738205/1229023). Do you really want to send the whole Error object to your client - or just its `message` property's value? – raina77ow Jun 28 '21 at 15:24
  • Well, I just wanted to populate some customized message if the error is regarding the database connection rather than not finding the user. – Kevin Martin Jun 28 '21 at 17:25
  • In this case, consider adding `type` to your response object and put `e.message` into `msg` instead of `Error found`. This `type` value might be a string or, better, one of predefined set of strings (enum). – raina77ow Jun 28 '21 at 17:27
  • Got it. Thanks for helping. :) – Kevin Martin Jun 28 '21 at 18:06
  • You're welcome. :) Should I post this as answer for you to accept? – raina77ow Jun 28 '21 at 18:18
  • Yeah, Sure. It will help others. – Kevin Martin Jun 28 '21 at 18:24

1 Answers1

0

The problem is that Error objects are not that easy to serialize (which is intentional). This...

try { 
  throw new Error('Catch me if you can');
} catch(e) { 
  console.log(JSON.stringify(e)); // {}
}

... just logs {}, the same as for empty object, because Error objects don't have enumerable properties. And in your case, you don't send that object directly - but make it a property of another object sent to client.

However, there are several ways out of this. If you always need your client to get all the details of an Error, cast that to string (as toString() is overridden):

try { 
  throw new Error('Catch me if you can');
} catch(e) { 
  console.log(JSON.stringify(e.toString())); // "Error: Catch me if you can"
}

... or use Error object properties - name and message - as separate fields of your response:

res.status(400).send({ 
  name: e.name || 'Anonymous Error',
  msg: e.message || 'no message provided' 
});

As sub-approach, you might consider choosing your status code based on type of error you have (always sending 404 for 'not founds', for example).

raina77ow
  • 103,633
  • 15
  • 192
  • 229