Express Js not sending error object on res.json() - node.js

getUser: function(req, res){
Model.getUser({}, function(error, models){
if(error){
let response = {
code: 'ERR0001',
msg: 'Facing issues while ....',
err: error
}
res.json(response);
} else {
res.json(models)
}
}
};
Above code is working fine for all positive scenarios. But for error scenario I am not getting complete error message instead it shows 'err: {}'.
I have already registered JSON parser with Express app object.
Response I am getting in POSTMAN console in case error is
{
code: 'ERR0001',
msg: 'Facing issues while ....',
err: {}
}
As per my requirement it should display something like:
{
code: 'ERR0001',
msg: 'Facing issues while ....',
err: 'ERROR: whatever exception occurred on database operation...'
}
Please help me to understand cause of this issue.

Express is stringifying your JSON response when you use res.json().
However, because the Error object doesn't get handled by JSON.stringify() as you would expect, you're not seeing the content of it; like the stack trace property for example.
For details on what's happening with JSON.stringify() and the Error object, check out this other stack overflow answer (I won't duplicate that here):
https://stackoverflow.com/a/18391400/2387067
So, using a variation of that answer, I will do this when I want to send back a Javascript Error object to the client from Express:
function replaceErrors(key, value) {
if (value instanceof Error) {
var error = {};
Object.getOwnPropertyNames(value).forEach(function (key) {
error[key] = value[key];
});
return error;
}
return value;
}
function getPureError(error) {
return JSON.parse(JSON.stringify(error, replaceErrors));
}
and then make a call to it in my response like this:
res.status(500).json(getPureError(error));
The call to getPureError() stringifys the Error object and gets all of the properties because of the call to replaceErrors(). It then parses it back to a pure object. That pure object plays nicely with Express when the .json() call is made so you get all of your properties that you were expecting. It is a bit wasteful but you get the result you're looking for.
This results in my seeing the full, Error object; stack trace and all.
When I first encountered this problem, I was doing this:
res.status(500).json(error);
and I was getting back {} in my response on the server. It took me a bit of time to sort out what was happening there. I originally thought that I wasn't chaining that json() command incorrectly but I was. The actual problem was that the Error object doesn't behave like other objects with JSON.stringify() as described above.
I hope that helps you or at least someone else after all this time!

Related

Firestore Transaction Error Appears as Empty Object

When I run a transaction inside a try {} catch(error){} block in Firestore, I noticed that when I try to store the error in logs, it appears as empty object. However, when I print it into console in the emulator, I get a proper error message.
Example code:
try {
await admin.firestore().runTransaction(async (t) => {
t.set(myRef, myNewData)
})
} catch(error) {
console.log(error) // This prints properly (e.g., "ReferenceError: myRef is not defined")
functions.logger.error(`Unexpected error occurred:`, { error: error }) // This prints error object as: "error: {}"
}
Why does the error object appear empty when using functions.logger.error() and how can I fix it?
If I'm not mistaken, this is because your { error: error } object isn't a simple object, which means the logger won't interpret it as a jsonPayload.
See more details in the doc ("If the last argument provided is a plain object, it is added to the jsonPayload in the Cloud Logging entry") and in this Github issue.
Potential solutions are as follows:
functions.logger.error(`Unexpected error occurred:`, error) // Here error is a "simple object"
functions.logger.error(`Unexpected error occurred:`, { error: error.message })
or the solution detailed in the Github issue.

Nodejs - Missing first character in error prototype name in stack trace when failing chai test case

I'm using Express and I'm writing a test for some part of my code using Chai.
At some point, the tested code is expecting the next() function from Express, so I'm mocking it by making a very simple function like follows:
var next = function(err) {
if (err) {
done(err)
} else {
done(
}
}
Meaning that if the mocked next() function receives an err, then it would fail the test by calling done(err), and if not, if will successfully finish the test by calling done().
Now, this seems to be working, but for the case when an err is received, I'm getting a truncated stacktrace in the test output. Suppose the error received is of prototype SomeError which in turn extends the default Error prototype, then in the console I see the following:
omeError
at Foo.bar.yeah (lib/foo/bar/yeah.js:78:12)
at Blah.someFunction (node_modules/yeah/lib/index.js:145:16)
Note the missing capital S in omeError when in fact it should be SomeError.
Btw, if I do a console.log(err) I get the following:
{ [SomeError]
foo: 'bar',
foo2: 'yeah'
name: 'SomeError' }
So, it seems the error object has a correct name SomeError. Altough I'm not sure why the string representation of the error also includes [SomeError] as a first line, in which seems a non-json syntax...
Why is this happening? I'm assuming something asyncronous failing to capure the complete stacktrace or something like that? Or could it be related to how SomeError extends Error. None of the above?

Passing object to node's Error class returns an unaccessible object

I'm returning an Error object, to which I pass an object (instead of a simple message):
if (err) {
return myCallback(new Error({
error_code: 'sample_machine_readable_code',
error_message: 'There is an error in the response from the service.',
error: err
}));
}
And the result in the console is [Error: [object Object]]. I tried accessing its properties both as properties of an array and as an object, but always end up with undefined. JSON.stringify-ing it returns an empty object {}. By "accessing" I mean trying to log the error, f.e. with console.log(err); (which ends up in [object Object]) or err.message or err.Error, or err['Error'], but these were undefined.
I was reading through Node's Error class docs and it seemed like it's okay to pass objects. Am I mistaken? Should I just return a simple custom-constructed object instead of a new Error? Like that:
if (err) {
return myCallback({
error_code: 'sample_machine_readable_code',
error_message: 'There is an error in the response from the service.',
error: err
});
}
Cuz I just wanted to use more of what Node offers and to stick to some widely used convention instead of going "my own way".
What you can do, is simply create an instance of Error and assign custom properties to it, like this:
var error = new Error("There is an error in the response from the service");
error.error = err;
error.error_code = "sample_machine_readable_code"
return myCallback(error);

No error being thrown for undefined variable in node.js with express

I am running node.js with express. I wrote a node module with methods in it so when you go to
http://bla.com/module_name/method_name
it will run the method.
The method follows the typical style of
exports.method_name(req, res, next);
my main app does something like this:
app.all("*", resSetup, controller, render);
and controller is the thing that will call the method based on the path.
it seems that if there is an undefined variable error in the method, express will just hang there and not throw any error. Nothing will appear in the console log either. I can put a console message right before and after where the error occurs and the before will appear in the log, and after will not.
I can wrap it in a try/catch and get this:
[ReferenceError: blabla is not defined]
but no line numbers or anything.
My guess is that express is somehow preventing the errors from coming up. When I put the error in the function called "controller" that is directly in the route, it shows that error correctly.
It might not matter too much, but here is the code I am working on:
https://github.com/RobKohr/quick-site/blob/master/index.js
Line 189 is where the method call happens.
Building on Ruairi's comment above, I had this same issue with when using 'q' (https://github.com/kriskowal/q) and promises with express - node would hang and no error was generated.
By adding a catch to the end of the promise 'callback' chain I was able to see the error and print it to console etc.
The code ends up looking like:
export function index(req, res) {
//Create the 'promise'
var request = req.body;
var queryJobID = req.query.jobId;
console.log('queryJobID: ' + queryJobID);
var jobStatusPromsie = jobManager.job.getStatus(queryJobID);
Q.all([jobStatusPromsie])
.then(
function (result) {
var responseData = {};
console.log('Job Status Response received');
if (result != null) {
//Without the .catch below an error here will be 'silent'
console.log('jobStatus result: ' + util.inspect(result, false, null));
responseData['status'] = 'OK';
responseData['progress'] = result.progress;
res.json(responseData);
} else {
console.log('jobStatus Error');
responseData['status'] = 'Error';
}
res.json(responseData);
console.log('jobStatus Response data sent');
},
function (error) {
console.log('Error while getting job status:', error);
res.json("Error");
})
.catch(function(err) {
//handle errors
console.log('Promise error while getting job status:', err);
});
}
Express heavily relies on Nodes asynchronous nature. Seeing errors thrown like on line 30 would give me the creeps if I was maintaining this. Try refactoring your code to only use the next(err) pattern.
The reason that you app is hanging is that Express hasn't finished the HTTP response (eg: res.send()). This means you have broken plumbing where an Error has bubbled up the call stack but not redirected into the Express middleware pipeline. Try registering some error middleware to see if it gets called with your error.

AngularJS Mongoose error handling

I've build a simple application with AngularJS. Part of this application is calling REST services. For that, I'm using mongoose. Everything works great, but I'd like to better handle errors. A sample code could be :
Express:
DBCollection.find({}, function (err, tuples) {
if (err) {
console.log('Error!');
}
res.send(JSON.stringify(tuples));
});
AngularJS:
DBService.query(function (res) {
$scope.data.lists = res;
});
The problem I'm faced with is as follow. Imagine I've got an error on the mongodb server side. I've got an error, so I log it in the console and then ? What happens on the angularjs/front-end side ? If I send the error as a http response, I suppose angular would interpreate it as the response of the query but with unexpected content and produce an exception ? how to deal with that ?
Angular is like Santa, it knows when responses are bad or good. There are 2 solutions, ones solutions is to create an error handler on each request. The other is to use $httpProvider.interceptors to globally handle errors before they become a problem on an individual request level.
Option 1
DBService.query(function (res) {
scope.data.lists = res;
},function(errorResult){
console.log(errorResult); // <- take a peek in here, find something useful
});
Option 2
$httpProvider.interceptors.push(['$q',function($q) {
return {
'responseError': function(rejection) {
console.log(rejection); // <- take a peek in here, find something useful
return $q.reject(rejection);
}
}
}]);

Resources