Skip to content

TransactionRollbackError behavior isn't documented #269

@MarkSFrancis

Description

@MarkSFrancis

From the transaction docs, it appears that no error will be thrown by calling rollback() on a transaction, but doing so will throw a TransactionRollbackError. Should the docs be updated?

Documented behavior:
The code provided in the docs:

const db = drizzle(...)
await db.transaction(async (tx) => {
  const [account] = await tx.select({ balance: accounts.balance }).from(accounts).where(eq(users.name, 'Dan'));
  if (account.balance < 100) {
    await tx.rollback()
    return
  }
  await tx.update(accounts).set({ balance: sql`${accounts.balance} - 100.00` }).where(eq(users.name, 'Dan'));
  await tx.update(accounts).set({ balance: sql`${accounts.balance} + 100.00` }).where(eq(users.name, 'Andrew'));
});

seems to be misleading, as the await before tx.rollback() is a no-op, and the return underneath will never be called. What will actually happen is that rollback() will throw an error, which is uncaught in this code example.

Actual behavior:

const db = drizzle(...)
await db.transaction(async (tx) => {
  const [account] = await tx.select({ balance: accounts.balance }).from(accounts).where(eq(users.name, 'Dan'));
  if (account.balance < 100) {
    // Throws a `TransactionRollbackError`
    tx.rollback();
  }
  await tx.update(accounts).set({ balance: sql`${accounts.balance} - 100.00` }).where(eq(users.name, 'Dan'));
  await tx.update(accounts).set({ balance: sql`${accounts.balance} + 100.00` }).where(eq(users.name, 'Andrew'));
});

This suggests that throwing was unintentional behavior, but according to this issue in the drizzle-orm repo, it is intentional but undocumented.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions