{"record":{"id":"ad6b843188a52aa0","repo":"vitessio/vitess","slug":"failed-query-begin-err-s","errorCode":null,"errorMessage":"failed query BEGIN, err: %s","messagePattern":"failed query BEGIN, err: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/binlog/binlogplayer/binlog_player.go","lineNumber":445,"sourceCode":"\t\t\t\t\t\tlog.Info(msg)\n\t\t\t\t\t\tif err := blp.setVReplicationState(binlogdatapb.VReplicationWorkflowState_Stopped, msg); err != nil {\n\t\t\t\t\t\t\tlog.Error(fmt.Sprintf(\"Error writing stop state: %v\", err))\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn nil\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tlog.Info(fmt.Sprintf(\"Retrying txn in %v.\", blp.deadlockRetry))\n\t\t\ttime.Sleep(blp.deadlockRetry)\n\t\t}\n\t}\n}\n\nfunc (blp *BinlogPlayer) processTransaction(tx *binlogdatapb.BinlogTransaction) (ok bool, err error) {\n\ttxnStartTime := time.Now()\n\tif err = blp.dbClient.Begin(); err != nil {\n\t\treturn false, fmt.Errorf(\"failed query BEGIN, err: %s\", err)\n\t}\n\tfor i, stmt := range tx.Statements {\n\t\t// Make sure the statement is replayed in the proper charset.\n\t\tif dbClient, ok := blp.dbClient.(*dbClientImpl); ok {\n\t\t\tvar stmtCharset *binlogdatapb.Charset\n\t\t\tif stmt.Charset != nil {\n\t\t\t\tstmtCharset = stmt.Charset\n\t\t\t} else {\n\t\t\t\t// Streamer sends a nil Charset for statements that use the\n\t\t\t\t// charset we specified in the request.\n\t\t\t\tstmtCharset = blp.defaultCharset\n\t\t\t}\n\t\t\tif !proto.Equal(blp.currentCharset, stmtCharset) {\n\t\t\t\t// In regular MySQL replication, the charset is silently adjusted as\n\t\t\t\t// needed during event playback. Here we also adjust so that playback\n\t\t\t\t// proceeds, but in Vitess-land this usually means a misconfigured\n\t\t\t\t// server or a misbehaving client, so we spam the logs with warnings.\n\t\t\t\tlog.Warn(fmt.Sprintf(\"BinlogPlayer changing charset from %v to %v for statement %d in transaction %v\", blp.currentCharset, stmtCharset, i, tx))","sourceCodeStart":427,"sourceCodeEnd":463,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/binlog/binlogplayer/binlog_player.go#L427-L463","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before: connection expired during idle gap\n//   if err = blp.dbClient.Begin(); err != nil { ... }\n// after: validate/reconnect before beginning\n//   if err := blp.dbClient.Ping(); err != nil {\n//       if err := blp.dbClient.Reconnect(); err != nil { return false, err }\n//   }\n//   if err = blp.dbClient.Begin(); err != nil { ... }","handlingStrategy":"retry","validationCode":"// check target is writable and reachable before streaming\nvar readOnly bool\nif err := targetDB.QueryRow(\"SELECT @@read_only OR @@super_read_only\").Scan(&readOnly); err != nil {\n    return fmt.Errorf(\"cannot probe target: %w\", err)\n}\nif readOnly {\n    return errors.New(\"target MySQL is read-only; BEGIN will fail\")\n}","typeGuard":null,"tryCatchPattern":"err := binlogplayer.ApplyBinlogEvents(ctx, blp)\nif err != nil && strings.Contains(err.Error(), \"failed query BEGIN\") {\n    log.Warn(\"BEGIN failed — likely dead target connection; restarting stream\")\n    return restartStream(ctx, blp) // fresh dbClient\n}","preventionTips":["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"],"tags":["mysql","transaction","connection","binlog-player"],"backgroundTag":"mysql-connection-broken","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}