Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why does this mysql error causes nodejs to crash instead of going to the catch function?

I have a mysql statement that creates an entry, it has a .then function and a .catch function, but when the following error occurs:

TypeError('Bind parameters must not contain undefined. To pass SQL NULL specify JS null');

the server crashes instead of answering a 500 like defined in the .catch function

Note: I'm using the mysql2 library from npm with promises (require('mysql2/promise');)

Here's the code that calls it (req.params.account_name is undefined):

const CREATE_ACCOUNT_STATEMENT =
  'INSERT INTO `Accounts` (`account_token`, `account_name`) VALUES (?, ?)'

try {
  mysqlConnectionPool.execute(CREATE_ACCOUNT_STATEMENT, [
    account_token, account_name
  ])
  .then(() => {
    res.end(JSON.stringify({ token: account_token }))
  })
  .catch((e) => {
    debug(1, "error while trying to create account:", e)
    res.status(500).end("Internal Server Error")
  })
} catch(e) {
  debug(1, "error while trying to create account:", e)
  res.status(500).end("Internal Server Error")
}
like image 679
Tom Klino Avatar asked Oct 23 '18 12:10

Tom Klino


People also ask

How does node handle mysql errors?

createConnection(function(err, connection) { if (err) { console. log(err); res. send({ success: false, message: 'database error', error: err }); return; } connection. on('error', function(err) { console.

How does node handle DB error?

For operational errors, you should use Promise rejections or a try-catch block with async/await. You want to handle these errors asynchronously. It works well and is widely used. If you have a more complicated case like I explained above, you should use an event emitter instead.


2 Answers

Actually, @Quentine was close to the right thing...

It is "sort of" a bug in mysql2, i use sort-of because https://github.com/sidorares/node-mysql2/issues/902 suggests the development team of mysql2 is o.k. with it.

it is an issue with the way mysql2.pool passes the call to the created connection, which does not pass the exception to the wrapping promise.

I ended up making my own wrapping function to create the connection + call execute wrapped in proper promise handling.

import mysql = require('mysql2');
private async queryDB(query:string, useExecute: boolean = false, ...args:any[]) : Promise<any[]>
    {
        return new Promise<any[]>((resolve, reject)=>{
            for(var i = 0; i < args.length; ++i)
            {
                if(args[i]===undefined)
                    args[i] = null;
            }
            this.dbPool.getConnection((err, conn)=>{
                if(err){
                    reject(err);
                    return;
                }
                
                let cb = function(err: mysql.QueryError, results: any[], fields: mysql.FieldPacket[]) {
                    conn.release();
                    if(err)
                    {
                        reject(err);
                        return;
                    }
                    resolve(results);
                }
                if(useExecute)
                    conn.execute(query, args, cb);
                else
                    conn.query(query, args, cb);                
            });
        });
    }
like image 161
Tomer W Avatar answered Nov 14 '22 22:11

Tomer W


mysqlConnectionPool.execute is throwing the exception before creating a promise.

i.e. the exception is not thrown from within the promise.

To catch it you would need to try {} catch (e) {} around the call to mysqlConnectionPool.execute.

like image 30
Quentin Avatar answered Nov 14 '22 23:11

Quentin