vitessio/vitess · error

type PRIMARY cannot restore from backup, if you really need

Error message

type PRIMARY cannot restore from backup, if you really need to do this, restart vttablet in replica mode

What it means

RestoreFromBackup refuses to run on a tablet the topology reports as PRIMARY, since restoring would wipe/replace a serving primary's data. The error directs you to restart the tablet as a replica type before restoring.

Source

Thrown at go/vt/vttablet/tabletmanager/rpc_backup.go:220

	defer func() {
		if startTime.IsZero() {
			return
		}
		tm.QueryServiceControl.BroadcastHealth()
		tm.invokeRestoreDoneHook(startTime, restoreErr, backupEngine)
	}()

	if err := tm.lock(ctx); err != nil {
		return err
	}
	defer tm.unlock()

	tablet, err := tm.TopoServer.GetTablet(ctx, tm.tabletAlias)
	if err != nil {
		return err
	}
	if tablet.Type == topodatapb.TabletType_PRIMARY {
		return errors.New("type PRIMARY cannot restore from backup, if you really need to do this, restart vttablet in replica mode")
	}

	// Create the logger: tee to console and source.
	l := logutil.NewTeeLogger(logutil.NewConsoleLogger(), logger)

	// Now we can run restore.
	startTime = time.Now()
	backupEngine, restoreErr = tm.restoreBackupLocked(ctx, l, 0 /* waitForBackupInterval */, true /* deleteBeforeRestore */, request, mysqlShutdownTimeout)

	return restoreErr
}

func (tm *TabletManager) IsBackupRunning() bool {
	return tm._isBackupRunning
}

func (tm *TabletManager) beginBackup(backupMode string) error {
	tm.mutex.Lock()

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Demote/remove the tablet from primary duty (reparent to another tablet) first
  2. Restart vttablet in REPLICA type (edit the type in topo or start with the appropriate type) and then run the restore
  3. Verify with vtctldclient GetTablets that the target is no longer PRIMARY before restoring

Example fix

// before
vtctldclient RestoreFromBackup alias-1  # alias-1 is PRIMARY
// after
vtctldclient PlannedReparentShard ks -new-primary alias-2
# restart alias-1 as replica, then:
vtctldclient RestoreFromBackup alias-1
Defensive patterns

Strategy: validation

Validate before calling

tablet, err := ts.GetTablet(ctx, alias)
if err != nil { return err }
if tablet.Type == topodatapb.TabletType_PRIMARY {
    return fmt.Errorf("cannot restore %s: demote/restart as replica first", topoproto.TabletAliasString(alias))
}

Try / catch

err := tm.RestoreFromBackup(ctx, logger)
if err != nil && strings.Contains(err.Error(), "cannot restore from backup") {
    return fmt.Errorf("tablet is PRIMARY in topo; reparent then restart as replica before restore")
}

Prevention

When it happens

Trigger: Calling RestoreFromBackup (vtctldclient RestoreFromBackup) against a tablet whose topo record has Type PRIMARY.

Common situations: Restoring a tablet that was accidentally promoted; emergency restore tooling pointed at the wrong alias; primary tablet being rebuilt without first being demoted/restarted as replica.

Related errors


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