vitessio/vitess · error

running MySQL version %q is too new for backup MySQL version

Error message

running MySQL version %q is too new for backup MySQL version %q

What it means

Thrown when the backup and running versions sit in the LTS upgrade-path walk but the running version goes beyond the allowed next-LTS target. The loop found parsedFrom in ltsVersions, parsedTo is not the immediately next LTS entry, and parsedTo >= parsedFrom, so the restore is rejected as 'too new'.

Source

Thrown at go/vt/mysqlctl/backupengine.go:703

	// If something is across different LTS streams and not upgrade safe, we can't use it.
	if !parsedFrom.isSameRelease(parsedTo) {
		if !upgradeSafe {
			if parsedTo.atLeast(parsedFrom) {
				return fmt.Errorf("running MySQL version %q is newer than backup MySQL version %q which is not safe to upgrade", to, from)
			}
			return fmt.Errorf("running MySQL version %q is older than backup MySQL version %q", to, from)
		}

		// Alright, we're across different LTS streams and the backup is upgrade safe.
		// We can only upgrade to the next LTS version.
		for i, ltsVersion := range ltsVersions {
			if parsedFrom.isSameRelease(ltsVersion) {
				if i < len(ltsVersions)-1 && parsedTo.isSameRelease(ltsVersions[i+1]) {
					return nil
				}
				if parsedTo.atLeast(parsedFrom) {
					return fmt.Errorf("running MySQL version %q is too new for backup MySQL version %q", to, from)
				}
				return fmt.Errorf("running MySQL version %q is older than backup MySQL version %q", to, from)
			}
		}
		if parsedTo.atLeast(parsedFrom) {
			return fmt.Errorf("running MySQL version %q is newer than backup MySQL version %q which is not safe to upgrade", to, from)
		}
		return fmt.Errorf("running MySQL version %q is older than backup MySQL version %q", to, from)
	}

	// At this point we know the versions are not the same, but we're withing the same version stream
	// and only the patch version number mismatches.

	// Starting with MySQL 8.0.35, the data dictionary format is stable for 8.0.x, so we can upgrade
	// from 8.0.35 or later here, also if the backup was taken with innodb_fast_shutdown=0.
	// This also applies for any version newer like 8.4.x.
	if parsedFrom.atLeast(mysql8035) && parsedTo.atLeast(mysql8035) {
		return nil

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Restore onto a tablet running the immediately next LTS version after the backup's version, then upgrade stepwise (restore -> upgrade -> next).
  2. Take a new backup on a version that is upgrade-safe for the desired target and restore from that.
  3. Pin the tablet's MySQL version to one covered by the backup's upgrade path.
  4. Plan upgrades against vitess's ltsVersions list and MySQL's supported in-place upgrade paths.

Example fix

// before: 8.0.x backup restored directly onto latest 8.4/9.x -> 'too new'
// after: restore onto next LTS first, then stepwise upgrade and re-backup
Defensive patterns

Strategy: validation

Validate before calling

if skippingLTS(backupVer, runningVer) {
    return errors.New("restore path skips an LTS: restore stepwise or retake backup")
}

Prevention

When it happens

Trigger: Restore where parsedFrom matches an ltsVersions entry, parsedTo is not the immediate next LTS entry (i+1), and parsedTo.atLeast(parsedFrom) — e.g. skipping an LTS by restoring an older-LTS backup onto a tablet two or more LTS streams ahead.

Common situations: Skipping LTS versions during upgrade (8.0 backup restored straight to a far-newer LTS); rebuilt tablet configured with a much newer mysqld than the backup.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/f7e5146697a6a5ce. Report an issue: GitHub.