vitessio/vitess · error · ErrMySQLShellPreCheck
%w: "skipBinlog" needs to set to true
Error message
%w: "skipBinlog" needs to set to true
What it means
restorePreCheck requires mysql-shell's load dump utility to run with skipBinlog=true. During a Vitess restore, replication recovery is driven by the restored GTID position and applying the load through the binary log would be wrong and slow. The check rejects any loadFlags where "skipBinlog" is missing or not the boolean true.
Source
Thrown at go/vt/mysqlctl/mysqlshellbackupengine.go:519
return shouldDeleteUsers, fmt.Errorf("%w: at least the --js flag is required in the value of the flag --mysql-shell-flags", ErrMySQLShellPreCheck)
}
loadFlags := map[string]any{}
err = json.Unmarshal([]byte(mysqlShellLoadFlags), &loadFlags)
if err != nil {
return false, fmt.Errorf("%w: unable to parse JSON of load flags", ErrMySQLShellPreCheck)
}
if val, ok := loadFlags["updateGtidSet"]; !ok || val != "replace" {
return false, fmt.Errorf("%w: mysql-shell needs to restore with updateGtidSet set to \"replace\" to work with Vitess", ErrMySQLShellPreCheck)
}
if val, ok := loadFlags["progressFile"]; !ok || val != "" {
return false, fmt.Errorf("%w: \"progressFile\" needs to be empty as vitess always starts a restore from scratch", ErrMySQLShellPreCheck)
}
if val, ok := loadFlags["skipBinlog"]; !ok || val != true {
return false, fmt.Errorf("%w: \"skipBinlog\" needs to set to true", ErrMySQLShellPreCheck)
}
if val, ok := loadFlags["loadUsers"]; ok && val == true {
shouldDeleteUsers = true
}
if mysqlShellSpeedUpRestore {
version, err := params.Mysqld.GetVersionString(ctx)
if err != nil {
return false, fmt.Errorf("%w: failed to fetch MySQL version: %v", ErrMySQLShellPreCheck, err)
}
_, sv, err := ParseVersionString(version)
if err != nil {
return false, fmt.Errorf("%w: failed to parse MySQL version (version: %s): %v", ErrMySQLShellPreCheck, version, err)
}
versionStr := fmt.Sprintf("%d.%d.%d", sv.Major, sv.Minor, sv.Patch)View on GitHub (pinned to 01a25a7d17)
Solutions
- Set "skipBinlog" to boolean true in the loadFlags map of the mysql-shell backupengine config
- Ensure it is a real boolean, not the string "true" (YAML unquoted, JSON without quotes)
- Re-check the sibling required flags: updateGtidSet=replace and progressFile empty
Example fix
// before
"loadFlags": {"updateGtidSet": "replace", "skipBinlog": "true"}
// after
"loadFlags": {"updateGtidSet": "replace", "skipBinlog": true} Defensive patterns
Strategy: validation
Validate before calling
if v, ok := loadFlags["skipBinlog"]; !ok || v != true {
return fmt.Errorf("mysql-shell loadFlags.skipBinlog must be boolean true")
} Try / catch
if _, err := engine.ExecuteRestore(ctx, params, backupDir); err != nil {
if errors.Is(err, mysqlctl.ErrMySQLShellPreCheck) {
// inspect and correct loadFlags before re-running restore
}
} Prevention
- Write skipBinlog as an unquoted boolean in YAML/JSON configs
- Include all three required flags (updateGtidSet, progressFile, skipBinlog) in a config template
- Lint configs for boolean-vs-string mistakes at deploy time
When it happens
Trigger: ExecuteRestore -> restorePreCheck when loadFlags["skipBinlog"] is absent, set to false, or set to a non-boolean value (e.g. string "true"), which fails the `!= true` comparison.
Common situations: Operators add skipBinlog as a YAML/JSON string "true" instead of boolean true; the flag is simply omitted from a hand-written loadFlags block; a config translated from a mysql-shell CLI example omits the flag because it isn't a CLI flag on their shell version.
Related errors
- %w: "progressFile" needs to be empty as vitess always starts
- %w: failed to fetch MySQL version: %v
- %w: failed to parse MySQL version (version: %s): %v
- %w: error checking if server supports disabling redo log: %v
- %w: MySQL version doesn't support disabling the redo log (mu
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/b2736efb312a6ca2.
Report an issue: GitHub.