sql.ErrTxDone
GoERRORNotableDatabase
sql: transaction has already been committed or rolled back
Quick Answer
Do not call Rollback after a successful Commit; use a deferred rollback that ignores sql.ErrTxDone.
What this means
Returned when an operation is called on a *sql.Tx after it has already been committed or rolled back. Common with deferred rollback patterns.
Why it happens
- 1Rollback called after Commit already succeeded
- 2Commit or Rollback called more than once on the same transaction
Fix
Ignore ErrTxDone in deferred rollback
Ignore ErrTxDone in deferred rollback
defer func() {
if err := tx.Rollback(); err != nil &&
!errors.Is(err, sql.ErrTxDone) {
log.Println("rollback:", err)
}
}()Why this works
Ignoring ErrTxDone in the deferred rollback is the standard Go transaction pattern.
Code examples
Deferred rollback patterngo
tx, _ := db.Begin() defer tx.Rollback() // safe to ignore ErrTxDone // ... do work tx.Commit()
Detectgo
err := tx.Rollback()
if errors.Is(err, sql.ErrTxDone) {
fmt.Println("already done")
}Named return patterngo
func run(db *sql.DB) (err error) {
tx, _ := db.Begin()
defer func() {
if err != nil { tx.Rollback() }
}()
return tx.Commit()
}Same error in other languages
Sources
Official documentation ↗
Go standard library
Content generated with AI assistance and reviewed for accuracy. Found an error? hello@errcodes.dev