Node-postgres: UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 22): ReferenceError: client is not defined

Created on 25 May 2017  路  4Comments  路  Source: brianc/node-postgres

I posted this question on Stack Overflow and the recommendation I got was to switch to pg-promise. Does node-postgres work with async-await?

This error seems to be coming up on every http request I make. I'm not totally sure where it's coming from?

(node:39390) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 22): ReferenceError: client is not defined

There is no line number in the error, but here is a sample of code that seems to be causing it:

    try {
        var client = await pool.connect();
        await client.query(queryStatement, queryArgumentsArray);
        res.sendStatus(200);
    } catch (e) {
        console.log('Error adding updating subvendor availability data, UPDATE SQL query task', err);
        res.sendStatus(500);
    } finally {
        client && client.release && client.release();
    }

It first I thought it must be coming from my finally block (maybe client was out of scope), but I added and if statement to explicitly prevent attempting to call client.release if it doesn't exist:

    if (client) { client && client.release && client.release() };

I am still getting this error, so I feel like it must be coming from these lines.

    var client = await pool.connect();
    await client.query(queryStatement, queryArgumentsArray);
    res.sendStatus(200);

Am I misunderstanding how to use async? To be clear, the code is functioning well and the http requests are working (responding correctly to the requests), my terminal is just getting flooded with these warnings.

Here is a simplified version of the full route:

    var express = require('express');
    var router = express.Router();
    var pool = require('../modules/pg-pool'); // brings in pg-pool created in another module

    // This route updates the availability for a user
    router.put('/updateAvailability', async (req, res) => {
        var userId = req.decodedToken.userSQLId;
        var subvendorId = req.headers.subvendor_id;
        var availability = req.body;

        var queryStatement = 'UPDATE status SET status=$3 WHERE userId=$2';
        var queryArgumentsArray = [availability.status, userId ];

        try {
            var client = await pool.connect();
            await client.query(queryStatement, queryArgumentsArray);
            res.sendStatus(200);
        } catch (e) {
            console.log('Error updating subvendor availability data, UPDATE SQL query task', err);
            res.sendStatus(500);
        } finally {
            client && client.release && client.release();
        }
    });

    module.exports = router;

Most helpful comment

node-postgres works fine with async/await. I use it all the time! There are a few things going on in your route handler that might be causing an issue, and I don't think any of them are related to node-postgres.

1) your route handler is an async function (basically a function that itself returns a promise) but express out of the box doesn't support returning promises from route handlers. It expects you to handle a route error by calling next in continuation passing or callback style. Try using this: express-promise-router - I usually use it in my projects & have had great success with it in the past. It will at least capture the rejected promise and most likely show you more info about where/why it was rejected.

2) the query you're using has params $2 and $3 but not $1 - unless I'm missing something that's not going to work - you can't "skip" a query param number with postgres.

3) you're assigning the value of client inside the try block. I know var client should be hoisted to the top of the function, but you could try assigning it outside the try block like so:

var client = await pool.connect()
try {
  await client.query(...)
  res.sendStatus(200)
} catch { ...} 
finally {

}

If you are using let instead of var in your actual code then that's definitely the problem. let has block-level scoping so client would be undefined in the finally block.

4) You probably want to do

finally {
  if(typeof client == 'undefined') {
    console.log('why is client undefined here?')
  } else {
    client.release()
  }
}

I hope those things help! You might also want to try attaching a debugger & stepping through line by line to see _exactly_ which line is throwing, or doing it old-school and just putting a ton more console.log statements in. :smile:

All 4 comments

node-postgres works fine with async/await. I use it all the time! There are a few things going on in your route handler that might be causing an issue, and I don't think any of them are related to node-postgres.

1) your route handler is an async function (basically a function that itself returns a promise) but express out of the box doesn't support returning promises from route handlers. It expects you to handle a route error by calling next in continuation passing or callback style. Try using this: express-promise-router - I usually use it in my projects & have had great success with it in the past. It will at least capture the rejected promise and most likely show you more info about where/why it was rejected.

2) the query you're using has params $2 and $3 but not $1 - unless I'm missing something that's not going to work - you can't "skip" a query param number with postgres.

3) you're assigning the value of client inside the try block. I know var client should be hoisted to the top of the function, but you could try assigning it outside the try block like so:

var client = await pool.connect()
try {
  await client.query(...)
  res.sendStatus(200)
} catch { ...} 
finally {

}

If you are using let instead of var in your actual code then that's definitely the problem. let has block-level scoping so client would be undefined in the finally block.

4) You probably want to do

finally {
  if(typeof client == 'undefined') {
    console.log('why is client undefined here?')
  } else {
    client.release()
  }
}

I hope those things help! You might also want to try attaching a debugger & stepping through line by line to see _exactly_ which line is throwing, or doing it old-school and just putting a ton more console.log statements in. :smile:

Does node-postgres work with async-await?

Yes; promises are produced by some parts of the API.

If you use pool.query to perform one query, does the error still occur?

await pool.query(
    'UPDATE status SET status = $1 WHERE userId = $2',
    [availability.status, userId]
)

Thank you @brianc! That did it! Because I moved it out of my try/catch block, I am nervous about an error connecting to the database not showing up in my terminal. Will var client = await pool.connect() throw that exception upwards?

@LukeSchlangen yah that will let the error propagate. Also it kinda makes sense semantically to have it outside the try/catch - if there's an error connecting a client, you wouldn't want to release it anyway (since it'd likely be undefined or in a broken state)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

KeynesYouDigIt picture KeynesYouDigIt  路  3Comments

tonylukasavage picture tonylukasavage  路  4Comments

gajus picture gajus  路  4Comments

wrod7 picture wrod7  路  4Comments

v1co1n picture v1co1n  路  4Comments