drizzle-team/drizzle-orm · warning · TransactionRollbackError
Rollback
Error message
Rollback
What it means
A TransactionRollbackError (subclass of DrizzleError) with message 'Rollback', thrown by MySqlTransaction.rollback() (drizzle-orm/src/mysql-core/session.ts:259). Calling tx.rollback() inside a db.transaction() callback is the documented way to abort; the thrown error unwinds the callback so the driver can issue ROLLBACK. It is expected control flow, not a defect, when the developer intentionally aborts.
Source
Thrown at drizzle-orm/src/mysql-core/session.ts:259
TQueryResult extends MySqlQueryResultHKT,
TPreparedQueryHKT extends PreparedQueryHKTBase,
TFullSchema extends Record<string, unknown> = Record<string, never>,
TSchema extends TablesRelationalConfig = Record<string, never>,
> extends MySqlDatabase<TQueryResult, TPreparedQueryHKT, TFullSchema, TSchema> {
static override readonly [entityKind]: string = 'MySqlTransaction';
constructor(
dialect: MySqlDialect,
session: MySqlSession,
protected schema: RelationalSchemaConfig<TSchema> | undefined,
protected readonly nestedIndex: number,
mode: Mode,
) {
super(dialect, session, schema, mode);
}
rollback(): never {
throw new TransactionRollbackError();
}
/** Nested transactions (aka savepoints) only work with InnoDB engine. */
abstract override transaction<T>(
transaction: (tx: MySqlTransaction<TQueryResult, TPreparedQueryHKT, TFullSchema, TSchema>) => Promise<T>,
): Promise<T>;
}
export interface PreparedQueryHKTBase extends MySqlPreparedQueryHKT {
type: MySqlPreparedQuery<Assume<this['config'], MySqlPreparedQueryConfig>>;
}
View on GitHub (pinned to b7862528fd)
Solutions
- Wrap db.transaction(...) in try/catch and check for TransactionRollbackError specifically; treat it as 'aborted by app', not a failure.
- Ensure your rollback is genuinely intentional; if it fired unexpectedly, find the code path that called tx.rollback().
- Do not swallow all errors — only swallow TransactionRollbackError when the abort was deliberate.
Example fix
// before
await db.transaction(async (tx) => {
await tx.insert(users).values(payload);
if (!valid) tx.rollback(); // throws TransactionRollbackError, unhandled
});
// after
import { TransactionRollbackError } from 'drizzle-orm/errors';
try {
await db.transaction(async (tx) => {
await tx.insert(users).values(payload);
if (!valid) tx.rollback();
});
} catch (e) {
if (e instanceof TransactionRollbackError) return { ok: false, reason: 'validation' };
throw e;
} Defensive patterns
Strategy: try-catch
Type guard
import { TransactionRollbackError } from 'drizzle-orm/errors';
function isIntentionalRollback(e: unknown): e is TransactionRollbackError {
return e instanceof TransactionRollbackError;
} Try / catch
try {
await db.transaction(async (tx) => {
await tx.insert(users).values(payload);
if (!valid) tx.rollback();
});
} catch (e) {
if (e instanceof TransactionRollbackError) {
return { ok: false, reason: 'business-rule validation aborted tx' };
}
throw e; // a real error
} Prevention
- Always wrap db.transaction() in try/catch and treat TransactionRollbackError as expected control flow.
- Only swallow TransactionRollbackError; rethrow everything else.
- Document that tx.rollback() throws, so teammates do not add a second throw handler.
When it happens
Trigger: Inside db.transaction(async tx => { ...; tx.rollback(); }), the explicit rollback() call throws this error to short-circuit the callback. Any caller that does not wrap the transaction in try/catch will see it propagate.
Common situations: A developer adds business-rule validation inside a transaction and calls tx.rollback() to cancel, but forgets that rollback() throws, so the error bubbles to an outer handler that treats it as a crash. Also common when porting code from a driver whose rollback does not throw.
Related errors
- Rollback
- Rollback
- Rollback
- Transactions are not supported by the MySql Proxy driver
- You have an empty array for "${name}" enum values
AI-assisted analysis of drizzle-team/drizzle-orm@b7862528fd (2026-08-03).
Data as JSON: /data/errors/f1686204450fd939.json.
Report an issue: GitHub.