How to make NodeJS carry on even if an error occurs? - javascript

I am building a simple login/register app. I am testing the login part. Whenever I input a wrong login, however, the backend (written in NodeJS and Express) crashes and stops.
Previously my code threw an error whenever the SQL returned error like so:
con.query("SELECT * FROM table_name WHERE username=" + usernameGiven, function(er, result) {
if (er) throw er;
return result;
}
This worked but had the issue as told above. So I removed the throw er part and replaced it with console.log(er) but still the nodeJS would stop and further login attempt will throw a CORS error.
So how can I stop it from doing and make it just log it and continue to the next request?
Edit:
I tried try and catch as shown below:
try {
con.query(sql_query, function(er, result) {
if (er) {
console.log(er);
}
response.json(result);
})
} catch (er) {
console.log(er);
}
However this still shows an error:
/home/x/CodeOver/LoginForm/api/node_modules/mysql/lib/protocol/Parser.js:437
throw err; // Rethrow non-MySQL errors
^
TypeError: Cannot read property 'password' of undefined
at Query.<anonymous> (/home/x/CodeOver/LoginForm/api/api.js:43:37)
at Query.<anonymous> (/home/x/CodeOver/LoginForm/api/node_modules/mysql/lib/Connection.js:526:10)

I'd suggest a little refactoring to make the code more robust to this type of failure.
The try .. catch blocks won't actually catch query errors in this situation, though I'll leave them there in case of any other error.
We should also use parameters here when querying. SQL Injection attacks are bad news and using parameters will also make the query less likely to result in a syntax error.
I'd also fail early and throw back a 400 error if our usernameGiven is not present.
Here is the updated code, I hope this helps you!
try {
if (!usernameGiven) {
response.status(400).send("Bad Request");
return;
}
let sql_query = "select * from table_name where username = ?";
con.query(sql_query, [usernameGiven], function(er, result) {
if (er) {
console.error("Error occurred:", er);
response.status(500).send("Internal Server Error")
} else {
response.json(result);
}
})
} catch (er) {
console.error("Error occurred:", er);
}

Related

How to access error message in the front end sent by the server?

In my node backend, this is how I send the error message to the front end:
catch (err) {
res.status(500).json("UNEXPECTED ERROR. Please try again later.");
}
How do I access the error message in the backend? Is this correct?
catch (err) {
err.response.data;
}
You can access the error message like: error.message
I have tried in typescript this worked for me.
try {
throw new Error("UNEXPECTED ERROR. Please try again later.");
} catch (error: any) {
console.log(error!.message);
return res.status(400).send(error!.message);
}

How to throw custom error in async callout

I'm making a couple async API callouts and may throw a custom error depending on the outcome.
I'm deleting Objects from S3.
try {
await s3.deleteObject(bucketParams);
//S3 API doesn't provide resp on if obj successfully deleted. Therefore, check that it doesn't exist afterwards to verify instead
const err = await s3.headObject(bucketParams);
if (err & err.code === 'NotFound') return { code:200, message:`${key} successfully deleted` }
throw `Error deleting ${key}`;
} catch (error) {
throw new Error(500, error);
}
So the main catch can handle any exceptions thrown by those couple API callouts (error with network, bad key, bad authorization, etc..)
However, if the object didn't actually get deleted (so if it still exists)..I throw a custom error to get reported back to end user.
My question is if there's a better pattern to just throwing a custom error in your try and then having it get slurped up by your catch.
Thanks!
You can do a lot to be honest, you just need to work out what you want to capture. Heres a basic example. If you were using TypeScript you would get more power and type safety
class S3ObjectNotFound extends Error {
// Add other attributes you might like
code
constructor(message) {
super(message)
this.name = 's3/object-id-not-found'
this.code = 404
}
}
const someFunction = async (bucketParmas, key) => {
try {
try {
await s3.deleteObject(bucketParams)
} catch (s3Error) {
throw new S3ObjectNotFound(`Object with id ${bucketParmas} was not found`)
}
const err = await s3.headObject(bucketParams)
if (err && err.code === 'NotFound') {
return { code: 200, message: `${key} successfully deleted` }
}
throw AnotherErrorYouCouldMake()
} catch (error) {
throw new Error(500, error)
}
}
someFunction({...YourParams}, 'YourKey')

Node.js MySQL error handling for pools and transactions

I want to start a transaction inside a pool connection. I found this code example in another StackOverflow question (link):
pool.getConnection(function(err, connection) {
connection.beginTransaction(function(err) {
if (err) { //Transaction Error (Rollback and release connection)
connection.rollback(function() {
connection.release();
//Failure
});
} else {
connection.query('INSERT INTO X SET ?', [X], function(err, results) {
if (err) { //Query Error (Rollback and release connection)
connection.rollback(function() {
connection.release();
//Failure
});
} else {
connection.commit(function(err) {
if (err) {
connection.rollback(function() {
connection.release();
//Failure
});
} else {
connection.release();
//Success
}
});
}
});
}
});
});
However I'm unsure about some specific lines in this example.
My first issue is in line 4 with the first connection.rollback(...). If beginTransaction() throws an error, why would you put a rollback here? If it couldn't start a transaction then there's nothing to rollback to, is there? Or is this just a security measure to close any potentially open transactions that may exist even though an error was thrown?
My second issue is with the rollback inside the commit. If the commit fails for whatever reason, wouldn't the rollback fail here as well? In what scenario could the commit fail but the following rollback succeed? Is there any reason other than network failure for the commit to fail?
The first question, rollback will do nothing. S
The second question depends on the error and database configuration. To be on the safe side, roll back after the error.

catch a specific type of exception in a javascript promise?

I am working with the node-instagram api (javascript). Occasionally, I get errors whenever I make a get request with the api. I want to display a particular error message when an ECONNRESET exception is raised, and then display a generic error message for all the other types of exception. My code so far looks like this:
instagram.get('users/self/media/recent').then(data => {
console.log(data)
}).catch(err => {
console.log(err)
});
How can I alter the promise to make it also recognise ECONNRESET exceptions and display a different error message when it catches them?
If you put a breakpoint on your console.log(err) and then inspect the err object when you hit the breakpoint, you should be able to tell what property on the err object tells you it was an ECONNRESET. Trincot says it's code. Then just use if:
instagram.get('users/self/media/recent').then(data => {
console.log(data)
}).catch(err => {
if (err.code === "ECONNRESET") {
throw new Error("Specific error message");
} else {
throw new Error("Generic error message");
}
});
In that code, I'm rethrowing the error so the promise is rejected, on the assumption that you're returning the result of this chain to something that will make use of its rejection reason. If you're just doing the message right there in that catch handler, then:
instagram.get('users/self/media/recent').then(data => {
console.log(data)
}).catch(err => {
if (err.code === "ECONNRESET") {
// Show the specific error message
} else {
// Show the generic error message
}
});
I would do Object.keys(err) in your catch block, to see the keys the error object provides. One of those keys should have the value with details to identify the type of error.
So for EXAMPLE:
console.log(Object.keys(err)) ----> ['type','status','description']
if(err.type === 'ECONNRESET' && err.status === {code identifying it}){
// do something
}

Returning error object along with the hapijs boom object

I'm trying to return the error object inside the response of a boom internal error object but it keeps omitting the error object.
I tried to follow the answer here but it didn't help.
function (request, reply) {
options.healthCheck(function (err) {
if (!err) {
return reply('I\'m healthy!!!');
}
var boomErr = boom.internal('I don\'t feel so good', {
err: err
});
boomErr.output.payload.details = err;
return reply(boomErr);
});
}
Here is the response:
{
"statusCode":500,
"error":"Internal Server Error",
"message":"An internal server error occurred",
"details":{ }
}
After digging into boom docs, I found out that all 5xx errors hide the custom message and payload.
Switching to bad request error solved my issue.

Categories