Firestore Transaction Error Appears as Empty Object - node.js

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.

Related

There is any way to handle errors with correct status code in NestJS or with GraphQL?

Actually, the GQL validation errors working correctly but when I throw the nestjs error with Exceptions of nestjs I don't get proper status code or exact error on the base array or inner objects the actual error found in the dept of the array. And in the browser network tab always show the 200 status even the nestjs throw an error, there is any way to catch the error which is thrown by the nestjs and correct status code in browser network tab when catch error?
The Apollo Server constructor accepts a formatError function that is run on each error passed back to the client. This can be used to mask errors as well as for logging and the in the NestJS you can use this method in your GraphQLModule mostly exists in the app.module.ts
GraphQLModule.forRoot({
....
...
formatError: (error) => {
const graphQLFormattedError = {
message:
error.extensions?.exception?.response?.message || error.message,
code:
error.extensions?.code || "SERVER_ERROR",
name: error.extensions?.exception?.name || error.name,
};
return graphQLFormattedError;
},
}),
I solved this type of problem by throwing grapqhl type error, where you can easily manage message and code.
throw new GraphQLError(
customMessage,
{
extensions: {
code: customCode,
},
},
);

Error when setting context... Cannot read property 'input' of undefined'

The error is:
TypeError: Cannot read property 'input' of undefined'
I am setting the context like so:
conv.contexts.set('pgnotes',1000,
{ 'pg':pgContext.pg,
'notes':response,
'lastReferencedPage':-1
}
);
I have set contexts using the same general code successfully in other areas. I'm not sure why it's an error here.
I'v submitted the question to actions on google support but I don't expect them to respond. Hoping someone here can offer an idea!
Some surrounding code
APIGetNotes(pgContext.pg, uniqname).then(
response=>{
console.log("conv.contexts %O", conv.contexts);
console.log("pgContext.pg: "+pgContext.pg);
console.log("notes: %O",response);
console.log("About to set context");
conv.contexts.set('pgnotes',1000,
{ 'pg':pgContext.pg,
'notes':response,
'lastReferencedPage':-1
}
);
respondBrowseNote(conv);
}
).catch(
error=>{
console.log("ERROR getting notes for pg '"+pgContext.pg+"' Error:'"+error+"'");
conv.ask("There was an error getting notes, try again later");
}
)

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 first-error

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.

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