diff --git a/lib/transaction.js b/lib/transaction.js index 46a897fcd9..4467ef6777 100644 --- a/lib/transaction.js +++ b/lib/transaction.js @@ -275,13 +275,7 @@ function makeTransactor(trx, connection, trxClient) { return trxClient.transaction(container, options, trx); } else { return new Promise((resolve, _reject) => { - trxClient.transaction( - (nestedTrx) => { - resolve(nestedTrx); - }, - options, - trx - ); + trxClient.transaction(resolve, options, trx).catch(_reject); }); } }; diff --git a/test/integration/builder/transaction.js b/test/integration/builder/transaction.js index e8e7065127..ff9afcfc49 100644 --- a/test/integration/builder/transaction.js +++ b/test/integration/builder/transaction.js @@ -728,4 +728,25 @@ module.exports = function(knex) { ).to.be.rejected; }); }); + + it('handles promise rejections in nested Transactions (#3706)', async function() { + const fn = sinon.stub(); + process.on('unhandledRejection', fn); + try { + await knex.transaction(async function(trx1) { + // These two lines together will cause the underlying Transaction + // to be rejected. Prior to #3706, this rejection would be unhandled. + const trx2 = await trx1.transaction(undefined, { + doNotRejectOnRollback: false, + }); + await trx2.rollback(); + + await expect(trx2.executionPromise).to.have.been.rejected; + }); + + expect(fn).have.not.been.called; + } finally { + process.removeListener('unhandledRejection', fn); + } + }); };