{"record":{"id":"758bf8ce4a332b2a","repo":"vitessio/vitess","slug":"w-mysql-shell-needs-to-restore-with-updategtidse","errorCode":null,"errorMessage":"%w: mysql-shell needs to restore with updateGtidSet set to \"replace\" to work with Vitess","messagePattern":"%w: mysql-shell needs to restore with updateGtidSet set to \"replace\" to work with Vitess","errorType":"error_code","errorClass":"ErrMySQLShellPreCheck","httpStatus":null,"severity":"error","filePath":"go/vt/mysqlctl/mysqlshellbackupengine.go","lineNumber":511,"sourceCode":"\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (be *MySQLShellBackupEngine) restorePreCheck(ctx context.Context, params RestoreParams) (shouldDeleteUsers bool, err error) {\n\tif mysqlShellFlags == \"\" {\n\t\treturn shouldDeleteUsers, fmt.Errorf(\"%w: at least the --js flag is required in the value of the flag --mysql-shell-flags\", ErrMySQLShellPreCheck)\n\t}\n\n\tloadFlags := map[string]any{}\n\terr = json.Unmarshal([]byte(mysqlShellLoadFlags), &loadFlags)\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"%w: unable to parse JSON of load flags\", ErrMySQLShellPreCheck)\n\t}\n\n\tif val, ok := loadFlags[\"updateGtidSet\"]; !ok || val != \"replace\" {\n\t\treturn false, fmt.Errorf(\"%w: mysql-shell needs to restore with updateGtidSet set to \\\"replace\\\" to work with Vitess\", ErrMySQLShellPreCheck)\n\t}\n\n\tif val, ok := loadFlags[\"progressFile\"]; !ok || val != \"\" {\n\t\treturn false, fmt.Errorf(\"%w: \\\"progressFile\\\" needs to be empty as vitess always starts a restore from scratch\", ErrMySQLShellPreCheck)\n\t}\n\n\tif val, ok := loadFlags[\"skipBinlog\"]; !ok || val != true {\n\t\treturn false, fmt.Errorf(\"%w: \\\"skipBinlog\\\" needs to set to true\", ErrMySQLShellPreCheck)\n\t}\n\n\tif val, ok := loadFlags[\"loadUsers\"]; ok && val == true {\n\t\tshouldDeleteUsers = true\n\t}\n\n\tif mysqlShellSpeedUpRestore {\n\t\tversion, err := params.Mysqld.GetVersionString(ctx)\n\t\tif err != nil {\n\t\t\treturn false, fmt.Errorf(\"%w: failed to fetch MySQL version: %v\", ErrMySQLShellPreCheck, err)","sourceCodeStart":493,"sourceCodeEnd":529,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/mysqlctl/mysqlshellbackupengine.go#L493-L529","documentation":"Vitess requires MySQL Shell's util.loadDump to run with updateGtidSet set to \"replace\" so the restored dump's GTID set is handled correctly for replication. restorePreCheck() wraps ErrMySQLShellPreCheck when the load flags lack the key or set it to anything other than \"replace\".","triggerScenarios":"ExecuteRestore -> restorePreCheck where the parsed --mysql-shell-load-flags JSON is missing \"updateGtidSet\" or has a value other than \"replace\" (e.g. \"append\" or \"disable\").","commonSituations":"Operators reusing load flags copied from vanilla MySQL Shell documentation/examples which default to a different updateGtidSet behavior; GTID replication setup on the tablet then fails or is inconsistent after restore.","solutions":["Set \"updateGtidSet\":\"replace\" in --mysql-shell-load-flags.","Re-validate the full required flag set: updateGtidSet=replace and progressFile empty.","After fixing, re-run the restore; the precheck aborts before any data is written so no cleanup is needed."],"exampleFix":"// before\n--mysql-shell-load-flags \"{\\\"updateGtidSet\\\":\\\"append\\\",\\\"progressFile\\\":\\\"\\\"}\"\n// after\n--mysql-shell-load-flags \"{\\\"updateGtidSet\\\":\\\"replace\\\",\\\"progressFile\\\":\\\"\\\"}\"","handlingStrategy":"validation","validationCode":"flags := map[string]any{}\nif err := json.Unmarshal([]byte(mysqlShellLoadFlags), &flags); err != nil {\n\treturn err\n}\nif v, ok := flags[\"updateGtidSet\"]; !ok || v != \"replace\" {\n\treturn errors.Errorf(\"updateGtidSet must be \\\"replace\\\" for Vitess restore, got %v\", v)\n}","typeGuard":null,"tryCatchPattern":"err := engine.ExecuteRestore(ctx, restoreParams)\nif strings.Contains(err.Error(), \"updateGtidSet\") {\n\t// correct --mysql-shell-load-flags to include \"updateGtidSet\":\"replace\"\n\treturn err\n}","preventionTips":["Pin the required load-flag pair (updateGtidSet=replace, empty progressFile) in your config template.","Do not copy util.loadDump examples from MySQL Shell docs verbatim into Vitess flags.","Add a CI config check asserting updateGtidSet==\"replace\" when the mysqlshell engine is enabled."],"tags":["restore","mysqlshell","gtid","configuration"],"backgroundTag":"invalid-json-config","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}