vitessio/vitess · error
failed query COMMIT, err: %s
Error message
failed query COMMIT, err: %s
What it means
Thrown by processTransaction when blp.dbClient.Commit() fails after all statements and the recovery-position write succeeded within the transaction. Because recovery info is written inside the same txn, a failed COMMIT means nothing (including the position) was persisted, so the whole transaction is retried from the stream.
Source
Thrown at go/vt/binlog/binlogplayer/binlog_player.go:492
if sqlErr, ok := err.(*sqlerror.SQLError); ok && sqlErr.Number() == sqlerror.ERLockDeadlock {
// Deadlock: ask for retry
log.Info(fmt.Sprintf("Deadlock: %v", err))
if err = blp.dbClient.Rollback(); err != nil {
return false, err
}
return false, nil
}
_ = blp.dbClient.Rollback()
return false, err
}
// Update recovery position after successful replay.
// This also updates the blp's internal position.
if err = blp.writeRecoveryPosition(tx); err != nil {
_ = blp.dbClient.Rollback()
return false, err
}
if err = blp.dbClient.Commit(); err != nil {
return false, fmt.Errorf("failed query COMMIT, err: %s", err)
}
blp.blplStats.Timings.Record(BlplTransaction, txnStartTime)
return true, nil
}
func (blp *BinlogPlayer) exec(sql string) (*sqltypes.Result, error) {
queryStartTime := time.Now()
qr, err := blp.dbClient.ExecuteFetch(sql, 0)
blp.blplStats.Timings.Record(BlplQuery, queryStartTime)
if d := time.Since(queryStartTime); d > SlowQueryThreshold {
log.Info(fmt.Sprintf("SLOW QUERY (took %.2fs) '%s'", d.Seconds(), sql))
}
return qr, err
}
// writeRecoveryPosition writes the current GTID as the recovery position
// for the next transaction.
// It also tries to get the timestamp for the transaction. Two cases:View on GitHub (pinned to 01a25a7d17)
Solutions
- Check the inner error: lock timeout → reduce competing writers or raise innodb_lock_wait_timeout; disk full → free space.
- Verify the last committed position in _vt.vreplication; nothing was committed for this txn, so a retry is safe.
- Restart the vreplication stream; it re-dials and re-applies from the stored position.
- Inspect target MySQL error log for deadlock/aborted transaction entries at the failure time.
Example fix
// before: lock wait timeout during commit // SET GLOBAL innodb_lock_wait_timeout = 60; -- or // after: remove competing writer on the target tables // (quiesce manual writes to replicated tables during vreplication)
Defensive patterns
Strategy: retry
Validate before calling
// pre-flight: ensure target is writable and has disk headroom
var readOnly bool
targetDB.QueryRow("SELECT @@read_only").Scan(&readOnly)
if readOnly {
return errors.New("target read-only; commits will fail")
}
// monitor df / MySQL free-space metrics on the target host Try / catch
err := binlogplayer.ApplyBinlogEvents(ctx, blp)
if err != nil && strings.Contains(err.Error(), "failed query COMMIT") {
// recovery info is in the same txn: nothing committed; retry is safe
log.Warn("COMMIT failed; transaction fully rolled back — retrying from stored position")
return retryWithBackoff(ctx, func() error {
return binlogplayer.ApplyBinlogEvents(ctx, blp)
})
} Prevention
- Quiesce external writers on replicated target tables to avoid lock timeouts
- Raise innodb_lock_wait_timeout if long replay transactions contend
- Monitor target disk space (commits fail when the disk fills)
- Check for deadlock victims in the target MySQL error log
When it happens
Trigger: dbClient.Commit() errors: connection dropped between last statement and COMMIT, MySQL killed the transaction (lock wait timeout, deadlock victim), target went read-only, disk full on target, or server crash during commit.
Common situations: Long transactions hitting innodb_lock_wait_timeout while other writers hold row locks; disk-full on the target host; network flap exactly at commit time; MySQL crash mid-commit causing recovery rollback.
Related errors
- failed query BEGIN, err: %s
- can't get charset to request binlog stream: %v
- no client certs for connection
- unexpected: query ended without no results and no error
- overflow
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/947df0edeb3c8553.
Report an issue: GitHub.