vitessio/vitess · error
could not get the original sql_mode on target: %v
Error message
could not get the original sql_mode on target: %v
What it means
setSQLMode first saves the target's current sql_mode so it can restore it later. It runs 'SELECT @@session.sql_mode' and requires exactly one row; if the query errors or returns an unexpected row count, this error is raised. The vreplication copy phase cannot proceed safely without capturing (then overriding) sql_mode.
Source
Thrown at go/vt/vttablet/tabletmanager/vreplication/vreplicator.go:664
_, err := dbClient.Execute(fmt.Sprintf("set @@session.foreign_key_checks=%d", vr.originalFKCheckSetting))
return err
}
func (vr *vreplicator) resetFKRestrictAfterCopy(dbClient *vdbClient) error {
if !vr.needFKRestrict() {
return nil
}
_, err := dbClient.Execute(fmt.Sprintf("set @@session.restrict_fk_on_non_standard_key=%d", vr.originalFKRestrict))
return err
}
func (vr *vreplicator) setSQLMode(ctx context.Context, dbClient *vdbClient) (func(), error) {
resetFunc := func() {}
// First save the original SQL mode if we have not already done so
if vr.originalSQLMode == "" {
res, err := dbClient.Execute(getSQLModeQuery)
if err != nil || len(res.Rows) != 1 {
return resetFunc, fmt.Errorf("could not get the original sql_mode on target: %v", err)
}
vr.originalSQLMode = res.Named().Row().AsString("sql_mode", "")
}
// Create a callback function for resetting the original
// SQL mode back at the end of the vreplication operation.
// You should defer this callback wherever you call setSQLMode()
resetFunc = func() {
query := fmt.Sprintf(setSQLModeQueryf, vr.originalSQLMode)
_, err := dbClient.Execute(query)
if err != nil {
log.Warn(fmt.Sprintf("Could not reset sql_mode on target using %s: %v", query, err))
}
}
vreplicationSQLMode := SQLMode
settings, _, err := vr.readSettings(ctx, dbClient)
if err != nil {
return resetFunc, errView on GitHub (pinned to 01a25a7d17)
Solutions
- Check the embedded cause (%v): if it is blank, the query succeeded but returned zero rows — investigate any proxy/intermediary between tablet and mysqld.
- Verify tablet-to-MySQL connectivity and that mysqld is up; reconnect/restart the tablet if the session was lost.
- Run 'SELECT @@session.sql_mode' manually as the tablet's MySQL user to confirm access.
- Restart the workflow so setSQLMode runs on a fresh, healthy connection.
Defensive patterns
Strategy: retry
Validate before calling
// Verify the tablet's MySQL user can read session sql_mode: // mysql -u <vtuser> -p -h <target> -e "SELECT @@session.sql_mode;" // Expect exactly one row with one column.
Try / catch
res, err := dbClient.Execute(getSQLModeQuery)
if err != nil || len(res.Rows) != 1 {
// reconnect or restart the stream; if err == nil, an intermediary
// is mangling the result — check for proxies
return resetFunc, retryAfterReconnect()
} Prevention
- Keep the tablet-mysqld connection healthy; monitor connection errors.
- Do not insert proxies that alter result sets of session-variable SELECTs.
- Grant the vt_dba-style user full session variable read access.
- Restart workflows after mysqld restarts instead of continuing on stale sessions.
When it happens
Trigger: Execute(getSQLModeQuery) returns an error (connection issue, permissions) OR len(res.Rows) != 1 — note a query error and empty result produce the same message, with err=nil in the empty-result case. Called by replicate and newClientConnection.
Common situations: Broken or just-reconnected MySQL connection; a proxy stripping or altering the SELECT result; mysqld restarted mid-copy; permission restrictions blocking @@session reads (rare, e.g. hardened setups).
Related errors
- could not set the permissive sql_mode on target using %s: %v
- partial row image encountered: ensure binlog_row_image is se
- can't get charset to request binlog stream: %v
- error in processing binlog event %v
- error %v in writing recovery info %v
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/52acf5f18b1f2902.
Report an issue: GitHub.