NestJS crashing on throwing http exception - nestjs

main.controller.ts:135
throw new NotFoundException('Swap not found');
^
NotFoundException: Swap not found
I have a pretty simple request in a controller
#Get("/details")
#ApiResponse({
status: 200,
description: 'Returns the details',
})
async getDetails(
#Query('id') id: string
): Promise<Result> {
let details = await this.databaseService.find(id)
if (!details) {
throw new NotFoundException('Swap not found');
}
return {
details: details,
}
}
After the exception is thrown, NestJS also stops from running!?
How do I avoid this? I know about the exception filters, but that's for custom exceptions, right? I use a default one.
Still, just in case, I've added a global one to test and same behaviour: app.useGlobalFilters(new HttpExceptionFilter());
Is this an expected behavior?

I faced the same issue, I fixed it by awaiting for the task to be done before throwing, I threw an error after sending the response, so I just added an await in my service where it is required.

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

Unhandled Error gets thrown in Firebase Cloud Functions

I'm using Firebase Cloud Functions, and in one of my projects I have a simple function that looks like the following:
exports.responseGiven = functions.https.onCall(async (data, context) => {
if (!context.auth) {
throw new functions.https.HttpsError(
'permission-denied',
'Must be an user to execute this action'
);
}
const studentPath = data.studentPath;
const eventPath = data.eventPath;
const isUpdating = data.isUpdating;
const studentDoc = await admin.firestore().collection('students').doc('studentPath').get();
const eventDoc = await studentDoc.ref.collection('entries').doc(eventPath).get();
});
I know where the error is through other methods and why it is, I'm using an invalidStudentPath. But the bigger issue is that the error that gets thrown is this for all of my errors in this project:
Unhandled error function error(...args) {
write(entryFromArgs('ERROR', args));
}
How can I get the actual error instead of this obscure message? Thanks for any help.
Update
I have found a workaround for now. Currently I'm wrapping my whole function in a try catch block that looks like this:
exports.responseGiven = functions.https.onCall(async (data, context) => {
try {
...
} catch (e) {
console.log('There was an error');
console.log(e);
}
});
The issue was fixed in firebase-functions v3.9.1. Alternatively you could downgrade to v3.8.0.
See https://github.com/firebase/firebase-functions/issues/757#issuecomment-673080726
I had a case recently where I forgot to await the result of an async (Promise-returning) function inside the relevant try / catch, so it escaped to the outer level. In the code I was working on, the logs look similar in the escaped case and catch error handler case. It is something that evaded my notice during unit testing because the functions were still triggering the node assert rejection hooks with the proper error messages.
I just got the same error on a new project. Took me a few hours to realize I forgot to initialize firebase admin after I imported it in my functions
import * as admin from 'firebase-admin';
admin.initializeApp();

Sinon spy fails with bad arguments for one function but succeeds for another identical one

I am really confused by the behaviour I'm seeing. My spy keeps misreporting the arguments. If I create identical functions with the same signature and arguments and spy on that separately then the copy works fine. I cannot work out what's going on!
So, here's the code:
NB: alert is the original function, test is the new one I created to check what's going on.
# index.js
class Alerter {
getOnErrorFn(name) {
return (error) => {
...
alert = {
opts: {
tags: 'Unknown Error'
}
}
...
if (alert) {
this.test(name, error.message, Object.assign({}, alert.opts, {smc_error: error.toLog()}), alert.level);
this.alert(name, error.message, Object.assign({}, alert.opts, {smc_error: error.toLog()}), alert.level); }
};
}
test(serviceName, message, opts={}, level=this.CRITICAL) {
console.log(serviceName, message, opts, level);
}
alert(serviceName, message, opts={}, level=this.CRITICAL) {
console.log(serviceName, message, opts, level);
...
}
Here's my test code (All other tests are commented out and this is the only file in the test suite);
# alerter.spec.js
const sandbox = sinon.sandbox.create();
describe('Alerter', function(){
let alerter;
let name = 'test-service';
let message = 'test message';
beforeEach(() => {
alerter = new Alerter(name);
});
afterEach(() => {
sandbox.restore();
});
describe('getOnErrorFn()', () => {
it.only('handles non-SMCError errors and assumes they should be alerted', () => {
const spy = sandbox.spy(alerter, 'test');
const spi = sandbox.spy(alerter, 'alert');
const onError = alerter.getOnErrorFn(name);
const error = new Error();
const smcError = SMCError.from(error);
onError(error);
expect(spy).to.have.been.calledWith(name, smcError.message, {smc_error: smcError.toLog(), tags: 'Unknown Error'}, undefined);
expect(spi).to.have.been.calledWith(name, smcError.message, {smc_error: smcError.toLog(), tags: 'Unknown Error'}, undefined);
});
});
});
And here's the result of the test run.... which is doing my absolute nut in!
$ npm test
> smc-alerting#2.1.3 test /Users/al/Studio/Projects/smc/app/smc-alerting
> mocha test/**/*.spec.js
Alerter
getOnErrorFn()
TEST test-service Caught Error { tags: 'Unknown Error',
smc_error: 'Error Caught Error\n caused by: Caught Error' } critical
ALERT test-service Caught Error { tags: 'Unknown Error',
smc_error: 'Error Caught Error\n caused by: Caught Error' } critical
1) handles non-SMCError errors and assumes they should be alerted
0 passing (34ms)
1 failing
1) Alerter getOnErrorFn() handles non-SMCError errors and assumes they should be alerted:
expected alert to have been called with arguments test-service, Caught Error, {
smc_error: "Error Caught Error
caused by: Caught Error",
tags: "Unknown Error"
}, undefined
alert(test-service, Caught Error, { smc_error: "Error Caught Error
caused by: Caught Error" }, undefined) at /Users/al/Studio/Projects/smc/app/smc-alerting/src/index.js:46:14
AssertionError: expected alert to have been called with arguments test-service, Caught Error, {
smc_error: "Error Caught Error
caused by: Caught Error",
tags: "Unknown Error"
}, undefined
alert(test-service, Caught Error, { smc_error: "Error Caught Error
caused by: Caught Error" }, undefined) at src/index.js:46:14
at Context.it.only (test/index.spec.js:173:32)
npm ERR! Test failed. See above for more details.
So, note that both console.log statements print identical results. BUT, the spy for the alert function fails with a printout that indicates that the function was called with the tags property missing from the third argument. WTF!
Or is there something I don't know happening here?
All help much appreciated. Thanks in advance!
Darnit. Got the answer. Long story short: use immutable objects!
alert() had a delete opts.tags line later down the code which of course changed the original object by the time sinon got round to checking it.

How to handle known errors that have no reason to be thrown

I am very aware of the problems with using uncaughtException in my code. I am also aware that the domains module is being deprecated so I do not want to use that. My question is what to do when I encounter an error that should not happen. For instance, if using mongo db and mongoose the following code example is give:
var kitty = new Cat({ name: 'Zildjian' });
kitty.save(function (err) {
if (err) {
console.log(err);
} else {
console.log('meow');
}
});
Here there is, what I assume is an inexplicable error. It is caught, but only uses console.log to log the error. Clearly more would have to happen to inform the user there is a problem, but I am wondering what should happen to the rest of the application.
Should it shutdown? Should something else happen? I have a good number of cases where I can catch errors like this, but if they happen they represent some very weird situation where something like the database has failed, or something else from another library has failed for no explicable reason and
I suggest you to return a json to your app showing the results of operation. Example:
if(err) {
res.status(500).json({saved: false, errormsg: 'Cannot save to database'});
} else {
res.json({saved: true, errormsg: null});
}
Handle the response in your app and show to the user that some bad think happened.

How to return an http error in a react component?

On the server side, how a reactjs component should notify the node application to return an http error?
My first idea was to throw an error:
var notFound = function () {
var error = new Error("Not Found");
error.httpError = 404;
throw error;
};
var App = React.createClass({
render: function () {
return react.DOM.div(null,
Locations({path: this.props.path},
Location({path: "/", handler: home}),
NotFound({handler: notFound})
)
);
}
});
try {
res.send(React.renderComponentToString(app()));
}
catch (err) {
if(err.httpError) {
res.send(err.httpError);
} else {
throw err;
}
}
Is it a valid solution? Do you have another idea in mind?
EDIT: I would like to extend this case to 3xx http redirection which are not errors. Does it change something?
I don't think this is related to React but actually to any framework.
I think this document can help you answer your own question:
https://www.joyent.com/developers/node/design/errors
However, you should check these (not enough) well known rules from the Java world:
Java Style: Properly handling exceptions
http://jtechies.blogspot.fr/2012/07/item-61-throw-exceptions-appropriate-to.html
You are throwing in your React app exceptions that do not belong to the http abstraction, and thus should not be aware of the http status codes. You should rather throw meaningful exceptions for the abstraction of rendering a React app in inline HTML, and then catch these exceptions and choose the appropriate error code in the catch block. This is just a detail for your implementation but on large code bases it matters.
By the way, you should not assume that exceptions you can catch are always exceptions you throw (ie wìll have the httpError property). Any code can throw an exception, even if you are pretty sure that it won't it's not a bad idea to handle this. If this happens, you may end up with a result being res.send(undefined); which will perhaps trigger another exception, and you won't have the cause of that exception because it was swallowed by your assumption that your code doesn't throw any unexpected exception.
Another principle to know is to fail fast. If you can handle the error before rendering, you would rather handle it before. Something like:
if ( ValidPaths.contains(path) ) {
render()
} else {
res.send(404)
}
If you have the possibility to handle the error without throwing an exception, just be aware that there is a cost to use exceptions, especially because of the stacktrace. There already have been DOS attacks on servers to generate a lot of exceptions on them. It is always better to not use exceptions for non exceptionnal things. Just be aware of it and choose yourself if a hacker trying to DOS you is exceptional or not :)
Anyway I think Javascript exception handling is a real pain :(

Resources