drizzle-team/drizzle-orm · error · TransactionRollbackError
Rollback
Error message
Rollback
What it means
TransactionRollbackError (message 'Rollback') thrown by SingleStoreTransaction.rollback() at session.ts:259. This is the documented mechanism to abort a transaction: calling tx.rollback() inside the transaction callback unwinds the transaction so the driver issues a ROLLBACK. It is intentional control flow, not an unexpected fault.
Source
Thrown at drizzle-orm/src/singlestore-core/session.ts:259
export abstract class SingleStoreTransaction<
TQueryResult extends SingleStoreQueryResultHKT,
TPreparedQueryHKT extends PreparedQueryHKTBase,
TFullSchema extends Record<string, unknown> = Record<string, never>,
TSchema extends TablesRelationalConfig = Record<string, never>,
> extends SingleStoreDatabase<TQueryResult, TPreparedQueryHKT, TFullSchema, TSchema> {
static override readonly [entityKind]: string = 'SingleStoreTransaction';
constructor(
dialect: SingleStoreDialect,
session: SingleStoreSession,
protected schema: RelationalSchemaConfig<TSchema> | undefined,
protected readonly nestedIndex: number,
) {
super(dialect, session, schema);
}
rollback(): never {
throw new TransactionRollbackError();
}
/** Nested transactions (aka savepoints) only work with InnoDB engine. */
abstract override transaction<T>(
transaction: (tx: SingleStoreTransaction<TQueryResult, TPreparedQueryHKT, TFullSchema, TSchema>) => Promise<T>,
): Promise<T>;
}
export interface PreparedQueryHKTBase extends SingleStorePreparedQueryHKT {
type: SingleStorePreparedQuery<Assume<this['config'], SingleStorePreparedQueryConfig>>;
}
View on GitHub (pinned to b7862528fd)
Solutions
- Catch TransactionRollbackError around the db.transaction call to treat it as an expected abort rather than a crash.
- Ensure business-logic aborts call tx.rollback() and nothing else throws raw errors for the same purpose.
- Do not swallow the error silently; log/handle it according to your rollback semantics.
Example fix
// before
await db.transaction(async (tx) => {
await tx.insert(users).values(payload);
if (!valid) tx.rollback();
});
// after
try {
await db.transaction(async (tx) => {
await tx.insert(users).values(payload);
if (!valid) tx.rollback();
});
} catch (e) {
if (e instanceof TransactionRollbackError) { /* expected abort */ }
else throw e;
} Defensive patterns
Strategy: try-catch
Type guard
import { TransactionRollbackError } from 'drizzle-orm/errors';
function isRollback(e): e is TransactionRollbackError { return e instanceof TransactionRollbackError; } Try / catch
import { TransactionRollbackError } from 'drizzle-orm/errors';
try {
await db.transaction(async (tx) => { if (!ok) tx.rollback(); });
} catch (e) {
if (e instanceof TransactionRollbackError) { /* expected */ return; }
throw e;
} Prevention
- Always wrap db.transaction in try/catch to handle intentional rollbacks.
- Use tx.rollback() as the sole mechanism to abort a unit of work.
- Do not let other accidental exceptions masquerade as rollbacks.
When it happens
Trigger: Inside db.transaction(async (tx) => { ... tx.rollback(); }), typically after a domain rule violation or business-logic check that should void the unit of work; also thrown by nested savepoint rollback.
Common situations: Multi-step writes where a later validation fails and earlier writes must be undone; intentional abort on conflicting concurrent state; tests that verify rollback behavior.
Related errors
- Rollback
- Rollback
- Rollback
- Transactions are not supported by the SingleStore Proxy driv
- Transactions are not supported by the MySql Proxy driver
AI-assisted analysis of drizzle-team/drizzle-orm@b7862528fd (2026-08-03).
Data as JSON: /data/errors/6b13ae2fc0979888.json.
Report an issue: GitHub.