I am trying to throw an error in the following syntex:
if(err) throw err
What I expect is to print the log by the line of "console.log(err)" instead of app crashed.
However, this occurs an error with app crashed and says
throw err; // Rethrow non-MySQL errors
^
Error: Error: ER_DUP_ENTRY: Duplicate entry 'test4' for key 'nickname_UNIQUE'
I cannot figure out why this happens and need helps from the experties.
code :
api.post('/', (req, res) => {
const email = req.body.email
const nickname = req.body.nickname
const password = req.body.password
const thumbnail = req.file
const type = req.body.type
const hasherCallback = (err, pass, salt, hash) => {
if (err) throw err
const sql = `INSERT INTO users set ?`
const fields = { nickname, email, 'password': hash, salt, thumbnail, type }
const queryCallback = (err) => {
if (err) throw err
return res.json(messages.SUCCESS_MSG)
}
conn.query(sql, fields, queryCallback)
}
try {
return hasher({ password }, hasherCallback)
} catch (err) {
//handle errors here
console.log(err)
}
})
return api
}
//Error : Error: Error: ER_DUP_ENTRY: Duplicate entry 'test4' for key 'nickname_UNIQUE'
The throw statement throws a user-defined exception. Execution of your function will stop and nothing will be executed from this point onwards.
See this website for help on the throw keyword. Also take the time to read about the throw new Error as this might be what you need instead of throw. This link may also be of help
In terms of why the error is occurring, the MySQL error is telling you you are inserting duplicate data into your users table. The database is rejecting it because a record already exists with the nickname value of 'test4' in the table.... So you are not allowed to insert another user with the same nickname of 'test4' into the table.
Why you may ask?
This is because You have an index on the table which requires the nickname to be unique.
Two options you could use are as follows:
Add more code to you javascript telling your user that if the nickname is already taken by another user, request that they choose another nickname and retry.
Allow duplicate nicknames by removing the unique nickname requirement on the table if you want to allow the same nickname to be inserted more than once. To do this you'll need to modify the index on the table. This may be dangerous and not suitable if your other table fields don't have a value that is unique.
Good luck and happy coding.
I found that I cannot throw errors in async function so I tried using callback.
api.post('/', (req, res) => {
const email = req.body.email
const nickname = req.body.nickname
const password = req.body.password
const thumbnail = req.file
const type = req.body.type
const errorHandle = (callback) => {
const hasherCallback = (err, pass, salt, hash) => {
if (err) return callback(err)
const sql = `INSERT INTO users SET ?`
const fields = { nickname, email, 'password': hash, salt, thumbnail, type }
const queryCallback = (err) => {
if (err) return callback(err)
return res.json(messages.SUCCESS_MSG)
}
conn.query(sql, fields, queryCallback)
}
return hasher({ password }, hasherCallback)
}
return errorHandle((err) => {
//This one equals console.log({ status: 'error' message: err })
return res.status(500).json(messages.ERROR(err))
})
})
This prints log what I want instead of app crashed.
{
"status": "error",
"message": {
"code": "ER_DUP_ENTRY",
"errno": 1062,
"sqlMessage": "Duplicate entry 'test4' for key 'nickname_UNIQUE'",
"sqlState": "23000",
"index": 0,
"sql": "INSERT INTO users SET `nickname` = 'test4', `email` = 'test4#test.com', `password` = 'FXxSpPBNFfL1KGS0sWn19N191Hj0FXtnCWwMspneVIvwB5UgPBI0MjBskEnHby357j/3VKWM7ffi/5yD5CiIRyAGMWnTaStzbVX/hhD1/y91UW9b8etWpV5koKcn9QsmD9BozX1+wkve66lTNoFUHDWA0BDj4j8O7ltsD4698LQ=', `salt` = 'cu7GlOjK4drxV/SD4CBJtiW5yirc5/TpaAroCBbCQtOy4Asr8rGvTrxArXHmPH6ADTtHlXvUEEoeUD73LS654Q==', `thumbnail` = NULL, `type` = 'local'"
}
}
Related
I am using postman with nodejs and MySQL.
Middleware
const notFound = (req, res, next) => {
const error = new Error(`Not Found -${req.originalUrl}`);
res.status(404);
next(error);
};
const errorHandler = (err, req, res, next) => {
const statusCode = res.statusCode === 200 ? 500 : res.statusCode;
res.status(statusCode);
res.json({
message: err.message,
stack: process.env.NODE_ENV === "production" ? null : err.stack,
});
};
export { notFound, errorHandler };
here I am trying to use notFound and errorHandler for the authUser
const authUser = asyncHandler(async (req, res) => {
const { email, password } = req.body;
let sql =
"select #uid :=`user_id`, first_name, last_name, email from dasa_user as var, (SELECT #uid := NULL) init_var where email=?;select #finaluid:= `user_id` from user_type, (SELECT #finaluid := NULL) init_var where user_id =#uid AND type='customer';select customer_id, password from customer where user_id =#finaluid;";
db.query(sql, [email], (err, result) => {
if (err) throw err;
if (result) {
if (result[2][0] == null) {
res.status(401);
throw new Error("user not Found");
} else {
if (MatchPassword(password, result[2]["0"]["password"])) {
res.json({
first_name: result[0][0]["first_name"],
last_name: result[0][0]["last_name"],
email: result[0][0]["email"],
userId: result[1]["0"]["#finaluid:= `user_id`"],
customerId: result[2]["0"]["customer_id"],
password: result[2]["0"]["password"],
token: generateToken(result[0][0]["email"]),
});
} else {
res.status(401);
throw new Error("Invalid email or password");
}
}
} else {
res.status(401);
throw new Error("Invalid email or password");
}
});
});
Now for this particular controller, I am accessing api/users/signin which is valid. But When I use something like api/users/signin/ksds. It does use notFound middleware and gives me error in postman. But in body If I use incorrect password, it should show error in postman console. But what it does it gives me error in vscode console. like this,
And I have to refresh the server everytime.
In order to access the notFoundanderrorHandler, I am using app.use` in server.js like this,
app.use(notFound);
app.use(errorHandler);
How can I solve this? So, that this will help me in showing error in the frontend too.
This errors comes in when you get empty results. You should first check the length of the results then use properties or index on it.
const authUser = asyncHandler(async (req, res) => {
const { email, password } = req.body;
let sql =
"select #uid :=`user_id`, first_name, last_name, email from dasa_user as var, (SELECT #uid := NULL) init_var where email=?;select #finaluid:= `user_id` from user_type, (SELECT #finaluid := NULL) init_var where user_id =#uid AND type='customer';select customer_id, password from customer where user_id =#finaluid;";
db.query(sql, [email], (err, result) => {
try {
if (err) throw err;
if (result.length > 0) {
if (result[2][0] == null) {
res.status(401);
throw new Error("user not Found");
} else {
if (MatchPassword(password, result[2]["0"]["password"])) {
res.json({
first_name: result[0][0]["first_name"],
last_name: result[0][0]["last_name"],
email: result[0][0]["email"],
userId: result[1]["0"]["#finaluid:= `user_id`"],
customerId: result[2]["0"]["customer_id"],
password: result[2]["0"]["password"],
token: generateToken(result[0][0]["email"]),
});
} else {
res.status(401); // this else is calling up for (If you use incorrect password)
throw new Error("Invalid email or password");
}
}
} else {
res.status(401).send({message: 'Results not found'}); // change this to send error message to the frontend, you can really customise it based on your needs.
// throw new Error("Results not found"); // Now this error is thrown because you don't have results
}
} catch (error) {
console.error(e);
}
});
});
But When I use something like api/users/signin/ksds. It does use
notFound middleware and gives me error in postman.
Because you are creating a custom error and sending it to node default error handler which does the work for you and postman receives the error message.
But in body If I use incorrect password, it should show error in
postman console. But what it does it gives me error in vscode console
However, in this case your are throwing an error and it is doing its job and you see that error in the console. If you don't want this behaviour follow the same flow as used above.
Check for more details: How to handle errors in Node.js?
I am using postman to send a request and I see Success message but in the database, it's not updated at all.
PostMAN request
database Snap shot
update services object: from this file I have used a database query to insert data in the database and set callBack funtion
const pool = require('../../config/database')
module.exports = {
updateUser: (data, callBack) => {
pool.query(
`UPDATE users SET firstName=?,email=?,password=?,lastName=?,phoneNumber=?, sex=? WHERE id=?`, [
data.firstName,
data.email,
data.password,
data.lastName,
data.phoneNumber,
data.sex,
data.id
], (error, results, fields) => {
if (error) {
return callBack(error)
}
return callBack(null, results)
}
)
}
}
update user controller here I have added a controller to update the user details which receive the data from update user services.
const {
create,
getUserbyID,
getUsers,
updateUser,
deleteUser,
getUserByEmail
} = require('./userService')
const {genSaltSync, hashSync, compareSync} = require('bcrypt')
const { sign } = require('jsonwebtoken')
module.exports ={
updateUser: (req, res) => {
const body = req.body;
const salt = genSaltSync(10);
body.password = hashSync(body.password, salt);
updateUser(body, (err, results) => {
if (err) {
console.log(err)
return false;
} // added
console.log("this is the body: "+JSON.stringify(req.body))
console.log("this is the results: "+ JSON.stringify(results))
if (!results) {
return res.json({
success:0,
message: "failed to update user"
})
}
return res.json({
success: 1,
message: "Updated Sucessfully"
})
})
},
}
router.js
router.patch('/update',checkToken, updateUser)
ADDED console.log
this is the body: {"Id":15,"firstName":"joey","email":"joey.chandler357#gmail.com","password":"$2b$10$ZBnRppSKAfQ1TrzGvs/wqOrVx/shb6ESJ7emXnC7IlWRN3VUGgfK2","lastName":"chandler","phoneNumber":"9860316634","sex":"Male"}
this is the results: {"fieldCount":0,"affectedRows":0,"insertId":0,"serverStatus":2,"warningCount":0,"message":"","protocol41":true,"changedRows":0}
I can see your console.log message
this is the results: {"fieldCount":0,"affectedRows":0,"insertId":0,"serverStatus":2,"warningCount":0,"message":"","protocol41":true,"changedRows":0}
Here you can notice affectedRows: 0 it means no row updated this happens when condition is not matched with any of the records. In postman you are passing "Id" I is in capital format but at the time of accessing this in service you are using "data.id" id is small latter so this is creating problem
we can handle this
instead of
if (!results) {
return res.json({
success:0,
message: "failed to update user"
})
}
use
if (!results.affectedRows) {
return res.json({
success:0,
message: "failed to update user"
})
}
this will be much better then previous check
I think you need to use an "insert" to add the db record. It's using an update... so it's looking for a pre-existing record.
Try two things:
wrap “users” in quotes on your update query. I’ve seen this w Postgres where some words are reserved in raw queries.
Examine the database response from your update. See what is console logged.
I got the Failed to load resource: the server responded with a status of 500 (Internal Server Error)
in the // Error inserting into users table section.
What causes this problem? Where should I check? My database has all the mandatory fields. I am using SQL db.
function registerUser(rBody) {
const connection = mysqlConnection
return new Promise((resolve, reject) => {
// First attempt to has user password, and continue on success
bcrypt.hash(rBody.password, 10, (err, hash) => {
if (err) {
// Error crypting password
resolve({
success: false,
error: 'Error hashing password'
})
} else {
// Build query & insert into users table
const valuesStr = `(null, "${rBody.email}", "${rBody.firstName}", "${rBody.lastName}", "${hash}", null, 2)`
const queryString = `INSERT INTO users values${valuesStr}`
connection.query(queryString, (err, resp) => {
if (err) {
// Error inserting into users table
resolve({
success: false,
error: err
})
} else {
// User succesfully created
resolve({
success: true,
message: 'User succesfully created',
id: resp.insertId
})
}
})
}
})
})
}
Edit your query to insert into the table does not seem to follow the standard syntaxis. Try
const queryString = `INSERT INTO users(name of your columns) VALUES(${valuesStr}`)
In mysql table i have created, I set autoincrement and unique value for the primary key. It is
I ran the following code multiple times. it is suppose to show error most of the time due to repetitive keys entered, however, there was no error.
exports.handler = async (event) => {
var mysql = require('mysql');
// TODO implement
var connection = mysql.createConnection({
host : '-',
user : '-',
password : '-',
database : '-'
});
const sql = `INSERT INTO forms VALUES(20,2,4,4,5,6,7,8,9,10,11);`;
connection.query(sql, (err, res) => {
if (err) {
throw err
}
})
const wait = () => {
setTimeout(()=>console.log('timeout'),2000)
}
await wait();
await console.log(sql)
const response = {
statusCode: 200,
body: JSON.stringify('Hello from Lambda!'),
};
return response;
};
It is suppose to show error as below
But it shows no error most of the time.Why?
I have a discord bot and I'm working on a command that shows info about a character(by providing the character name) from a mysql database. It works fine but if I provide a name that doesn't exist in the database like !characterinfo asdasfefcdce, the bot crashes. So my question is How do I prevent it from crashing if I provide a wrong name?. Hopefully you understand what I mean.
Here's the code:
const Discord = require('discord.js');
const mysql = require('mysql');
const {stripIndents} = require("common-tags");
const { prefix, token } = require('../config.json');
module.exports.run = async (bot, message, args, connection3) => {
if (message.content == '!characterinfo') {
return message.reply('provide a character name!');
}
const name = args[0];
connection3.query('SELECT * FROM characters WHERE name = ?', [name], function(err, results, rows) {
if (err) throw err;
const embed = new Discord.RichEmbed()
.setColor('RANDOM')
.setTitle('**Character Information**')
.addField('Nickname:', results[0].name)
.addField('Level:', results[0].level)
.setFooter(`test`)
.setTimestamp();
message.channel.send(embed);
});
}
module.exports.help = {
name: "characterinfo",
}
If you need me to provide you more info, let me know.
Any help is appreciated!
The bot crashes at the moment because in this line
if (err) throw err;
you throw an error and don't handle it later, the simplest way to change this is to replace throw by console.log or console.error
if (err) console.error(err);
Or you could keep the throw and wrap the code with a try/catch.
try {
connection3.query('SELECT * FROM characters WHERE name = ?', [name], function (err, results, rows) {
if (err) throw err;
const embed = new Discord.RichEmbed()
.setColor('RANDOM')
.setTitle('**Character Information**')
.addField('Nickname:', results[0].name)
.addField('Level:', results[0].level)
.setFooter(`test`)
.setTimestamp();
message.channel.send(embed);
});
} catch(err) {
// Handle the error ...
console.log(err)
}
EDIT: So the error is actually coming from the results array not having any entries when the query doesn't find a result, so this solution should work.
You should check to see if there's a "results" before doing anything else.
try {
connection3.query('SELECT * FROM characters WHERE name = ?', [name], function (err, results, rows) {
if (err) throw err;
if (!results[0]) return;
const embed = new Discord.RichEmbed()
.setColor('RANDOM')
.setTitle('**Character Information**')
.addField('Nickname:', results[0].name)
.addField('Level:', results[0].level)
.setFooter(`test`)
.setTimestamp();
message.channel.send(embed);
});
} catch(err) {
// Handle the error ...
console.log(err)
}