Node.js first-error - node.js

If I do:
const debug = require('debug')('app');
var err = new Error("my error");
debug(err);
err.message = "new error";
debug(err);
I do not see the new error message. But if I do:
debug(err.message);
I do see the new error message. My question is what is the 'err' really? Its typeof is object but why don't I see all of the objects parts?

When the debug library encounters an error, it logs error.stack, which is a pre-computed string that has the error message baked in. That's why changing the error message after the creation of the error does not appear to show up in your code, because the error.stack property has been set.
You can see that behavior on these lines:
if (val instanceof Error) return val.stack || val.message;
Either way you should not modify error messages after the error has been created.

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.

How to attach a key to error attribute when return error

I am using nodejs and I return my response as follows:
res.status(503).json({"error": {"retry": true}}).end();
In the UI I see
However this is not what I want. I need {"retry": true} be part of the error attribute. Is there a way I can do it?
This is how you create custom errors in javascript:
const err = new Error("some message")
err.retry = true;
In the response you can just attach the err variable to the error prop like this:
res.status(503).json({ error: err }).end()
EDIT
I believe the default props for an Error object are name, message and stack.

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

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!

Node.js: Unit testing, Expect error message when function requires specific value

I am new to unit testing, i was just doing random test for practice using mocha.js and expect
expect
mocha.js
I just have a problem on making the unit testing to expect a specific error when it's calling a function with wrong values
Function:
module.exports.parseOptions = function(opts){
if(utils.isFalsy(opts)){
throw new Error("Options is undefined");
}
else if(!utils.isObject(opts)){
throw new Error("Options parameter must be an object");
}
else{
// Path is mandatory for this package, throw error if undefined
if(!opts.path){
throw new Error("Path for static files is undefined");
}
.......
}
}
Unit test file:
var expect = require("expect");
var helper = require("./../lib/helper.js");
describe("helper functions", function(){
it("should parse options", function(){
//This process works fine
expect(function(){
helper.parseOptions();
}).toThrow("Options is undefined");
//This process fails for some reason
expect(function(){
helper.parseOptions([]);
}).toThrow("Options parameter must be an object");
});
})
What terminal shows:
helper functions
1) should parse options
0 passing (9ms)
1 failing
1) helper functions should parse options:
Error: Expected [Function] to throw 'Options parameter must be an object'
at assert (node_modules/expect/lib/assert.js:29:9)
at Expectation.toThrow (node_modules/expect/lib/Expectation.js:104:28)
at Context.<anonymous> (test/test-driven-development.js:12:6)
I am struggling to understand how it really works, i would like to make unit testing to validate all kind of errors as well with expected values, if there is any other tool more useful, please let me know
I just found the reason why the test is failing, looks like the parameter sent to the function is validating if it's falsy, meaning that [] value is falsy and so the function throws the error that the value is undefined
i had to change from:
module.exports.parseOptions = function(opts){
if(utils.isFalsy(opts)){
throw new Error("Options is undefined");
}
.......
}
to:
module.exports.parseOptions = function(opts){
if(typeof opts == "undefined"){
throw new Error("Options is undefined");
}
.......
}

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);

Resources