vitessio/vitess · error
failed query BEGIN, err: %s
Error message
failed query BEGIN, err: %s
What it means
Thrown by processTransaction when blp.dbClient.Begin() fails, meaning the player could not open a transaction on the target MySQL connection before replaying statements. The transaction is aborted before any statement is applied.
Source
Thrown at go/vt/binlog/binlogplayer/binlog_player.go:445
log.Info(msg)
if err := blp.setVReplicationState(binlogdatapb.VReplicationWorkflowState_Stopped, msg); err != nil {
log.Error(fmt.Sprintf("Error writing stop state: %v", err))
}
return nil
}
}
break
}
log.Info(fmt.Sprintf("Retrying txn in %v.", blp.deadlockRetry))
time.Sleep(blp.deadlockRetry)
}
}
}
func (blp *BinlogPlayer) processTransaction(tx *binlogdatapb.BinlogTransaction) (ok bool, err error) {
txnStartTime := time.Now()
if err = blp.dbClient.Begin(); err != nil {
return false, fmt.Errorf("failed query BEGIN, err: %s", err)
}
for i, stmt := range tx.Statements {
// Make sure the statement is replayed in the proper charset.
if dbClient, ok := blp.dbClient.(*dbClientImpl); ok {
var stmtCharset *binlogdatapb.Charset
if stmt.Charset != nil {
stmtCharset = stmt.Charset
} else {
// Streamer sends a nil Charset for statements that use the
// charset we specified in the request.
stmtCharset = blp.defaultCharset
}
if !proto.Equal(blp.currentCharset, stmtCharset) {
// In regular MySQL replication, the charset is silently adjusted as
// needed during event playback. Here we also adjust so that playback
// proceeds, but in Vitess-land this usually means a misconfigured
// server or a misbehaving client, so we spam the logs with warnings.
log.Warn(fmt.Sprintf("BinlogPlayer changing charset from %v to %v for statement %d in transaction %v", blp.currentCharset, stmtCharset, i, tx))View on GitHub (pinned to 01a25a7d17)
Solutions
- Check target MySQL connectivity and `wait_timeout`/`interactive_timeout`; increase if gaps between vreplication transactions are long.
- Verify the target is not read-only (`SELECT @@read_only, @@super_read_only`).
- Restart the vreplication stream to get a fresh dbClient connection.
- Check target MySQL error log for aborted connections around the failure time.
Example fix
// before: connection expired during idle gap
// if err = blp.dbClient.Begin(); err != nil { ... }
// after: validate/reconnect before beginning
// if err := blp.dbClient.Ping(); err != nil {
// if err := blp.dbClient.Reconnect(); err != nil { return false, err }
// }
// if err = blp.dbClient.Begin(); err != nil { ... } Defensive patterns
Strategy: retry
Validate before calling
// check target is writable and reachable before streaming
var readOnly bool
if err := targetDB.QueryRow("SELECT @@read_only OR @@super_read_only").Scan(&readOnly); err != nil {
return fmt.Errorf("cannot probe target: %w", err)
}
if readOnly {
return errors.New("target MySQL is read-only; BEGIN will fail")
} Try / catch
err := binlogplayer.ApplyBinlogEvents(ctx, blp)
if err != nil && strings.Contains(err.Error(), "failed query BEGIN") {
log.Warn("BEGIN failed — likely dead target connection; restarting stream")
return restartStream(ctx, blp) // fresh dbClient
} Prevention
- Set MySQL wait_timeout above the max gap between vreplication transactions
- Never put replicated targets in super_read_only while streams are active
- Monitor target MySQL error log for aborted connections
- Restart streams proactively after target MySQL maintenance restarts
When it happens
Trigger: dbClient.Begin() errors: target MySQL connection is dead/closed (server gone away, wait_timeout), the dbConn was closed by charset-restore defer from a previous run, or the target server refuses new transactions (read-only, killing connections).
Common situations: Target MySQL restarted or idle connection expired during a long gap between transactions; super_read_only enabled on the target; connection pool exhaustion causing the player's conn to be reaped.
Related errors
- can't get charset to request binlog stream: %v
- failed query COMMIT, err: %s
- no port variable in mysql
- no read_only variable in mysql
- can't get charset to check binlog stream: %v
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/ad6b843188a52aa0.
Report an issue: GitHub.