Nirvan bbs
Nirvan bbs

Reputation: 129

Unhanded rejection error :Transaction query already complete - knex, express.js

I was trying to check for a value in a table first, and if it exists, delete a row in another table and insert this new data into that table.

I used a transaction with a select, del(), and a insert command

db.transaction(trx => {
  return trx('users')
    .where({ username: user.username })
    .select('username')
    .returning('username')

    .then(retData => {
      retUserName = retData[0];

      db('profile')
        .where({ username: user.username })
        .del()
        .then(retData => {
          return trx
            .insert(profileData)
            .into('profile')
            .returning('*');
        });
    })
    .then(retData => {
      res.json({ ProfileData: profileData });
    })
    .then(trx.commit)
    .catch(trx.rollback);
}).catch(err => res.status(400).json('unable to create profile'));

I get this error Unhanded rejection error:Transaction query already completed

but the data hasn't been added to the table.

Upvotes: 9

Views: 16995

Answers (3)

If your up and down are async functions, make sure to await the knex.transaction call.

Problem: missing await

export async function up(knex: Knex): Promise<void> {
    knex.transaction(async (tx) => {});
//  ^ await is missing. This will error
}

Solution: use await

export async function up(knex: Knex): Promise<void> {
    await knex.transaction(async (tx) => {});
//  The `up` function will wait until the transaction finishes
}

Upvotes: 0

Mikael Lepist&#246;
Mikael Lepist&#246;

Reputation: 19718

You are returning promise from transaction handler callback, which causes transaction to automatically committed / rolled back depending if returned promise resolves / rejects.

https://knexjs.org/guide/transactions.html

Throwing an error directly from the transaction handler function automatically rolls back the transaction, same as returning a rejected promise.

Notice that if a promise is not returned within the handler, it is up to you to ensure trx.commit, or trx.rollback are called, otherwise the transaction connection will hang.

In your code you are mixing those two different ways to use transactions, which causes it to be committed / rolledback twice.

Upvotes: 18

Jose_Tandil
Jose_Tandil

Reputation: 31

I ran into different situation but same error. Perhaps it helps someone.

knex.transaction(async (t) => {
...

Using async function causes the same effect..

This worked

knex.transaction((t) => {
...

Upvotes: 3

Related Questions