{"record":{"id":"f93b44f6e325eeee","repo":"vitessio/vitess","slug":"running-mysql-version-q-is-newer-than-backup-mysq","errorCode":null,"errorMessage":"running MySQL version %q is newer than backup MySQL version %q which is not safe to upgrade","messagePattern":"running MySQL version %q is newer than backup MySQL version %q which is not safe to upgrade","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/mysqlctl/backupengine.go","lineNumber":690,"sourceCode":"\t}\n\n\tif flavorTo != flavorFrom {\n\t\treturn fmt.Errorf(\"cannot use backup between different flavors: %q vs. %q\", from, to)\n\t}\n\n\tif parsedTo == parsedFrom {\n\t\treturn nil\n\t}\n\n\t// If we're not on the same LTS stream, we have to do additional checks to see if it's safe to\n\t// to upgrade. It can only be one newer LTS version for the destination and the backup\n\t// has to be marked as upgrade safe.\n\n\t// If something is across different LTS streams and not upgrade safe, we can't use it.\n\tif !parsedFrom.isSameRelease(parsedTo) {\n\t\tif !upgradeSafe {\n\t\t\tif parsedTo.atLeast(parsedFrom) {\n\t\t\t\treturn fmt.Errorf(\"running MySQL version %q is newer than backup MySQL version %q which is not safe to upgrade\", to, from)\n\t\t\t}\n\t\t\treturn fmt.Errorf(\"running MySQL version %q is older than backup MySQL version %q\", to, from)\n\t\t}\n\n\t\t// Alright, we're across different LTS streams and the backup is upgrade safe.\n\t\t// We can only upgrade to the next LTS version.\n\t\tfor i, ltsVersion := range ltsVersions {\n\t\t\tif parsedFrom.isSameRelease(ltsVersion) {\n\t\t\t\tif i < len(ltsVersions)-1 && parsedTo.isSameRelease(ltsVersions[i+1]) {\n\t\t\t\t\treturn nil\n\t\t\t\t}\n\t\t\t\tif parsedTo.atLeast(parsedFrom) {\n\t\t\t\t\treturn fmt.Errorf(\"running MySQL version %q is too new for backup MySQL version %q\", to, from)\n\t\t\t\t}\n\t\t\t\treturn fmt.Errorf(\"running MySQL version %q is older than backup MySQL version %q\", to, from)\n\t\t\t}\n\t\t}\n\t\tif parsedTo.atLeast(parsedFrom) {","sourceCodeStart":672,"sourceCodeEnd":708,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/mysqlctl/backupengine.go#L672-L708","documentation":"Thrown by the backup restore version-compatibility check (checkRestoreVersion) in backupengine.go when the running MySQL version is newer than the version a backup was taken with, the versions are in different LTS release streams, and the backup is not marked upgrade-safe. Vitess refuses to restore such a backup because restoring an upgrade-unsafe backup onto a newer MySQL version can corrupt the data dictionary / system tables.","triggerScenarios":"Restore (BackupEngine.Restore / mysqlctl restore) where parsedTo.atLeast(parsedFrom) is true, !parsedFrom.isSameRelease(parsedTo) (different release streams, e.g. 8.0.x backup on 8.4.y tablet), and the backup manifest lacks the upgradeSafe marker.","commonSituations":"Operator upgraded a tablet's MySQL binary (8.0 -> 8.4) but existing backups were taken before the upgrade and are not upgrade-safe; restoring an old backup onto a newly provisioned, newer MySQL tablet.","solutions":["Take a fresh backup with the currently running (newer) MySQL version and restore from that backup instead.","Downgrade the tablet's mysqld back to the same release stream the backup was taken with, then restore.","Re-take the backup using a MySQL version that is upgrade-safe for the target version per MySQL's in-place upgrade rules, then retry the restore.","Verify the backup manifest's MySQLVersion was recorded correctly so upgradeSafe evaluation is accurate."],"exampleFix":"// before: restoring an 8.0.x backup onto an 8.4.x tablet fails\nmysqlctl restore ...\n// after: take a new backup with 8.4.3 running first, then restore\nmysqlctl backup  # with mysqld 8.4.3\nmysqlctl restore  # succeeds from the new backup","handlingStrategy":"validation","validationCode":"backupVer := parseVersion(backupManifest.MySQLVersion)\nrunningVer := parseVersion(getRunningMySQLVersion())\nif runningVer.atLeast(backupVer) && !backupVer.isSameRelease(runningVer) {\n    return errors.New(\"backup not restorable on newer MySQL: retake backup or use upgrade-safe backup\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Take a fresh backup immediately after upgrading MySQL on a shard.","Keep tablet MySQL versions aligned with the backup-producing versions.","Use only upgrade-safe backups for cross-stream restores.","Pin MySQL versions per keyspace and document upgrade procedures."],"tags":["mysql","backup","restore","version-compatibility","upgrade"],"backgroundTag":"mysql-backup-version-incompatible","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}