{"record":{"id":"7ca3846085022c7b","repo":"vitessio/vitess","slug":"type-primary-cannot-restore-from-backup-if-you-re","errorCode":null,"errorMessage":"type PRIMARY cannot restore from backup, if you really need to do this, restart vttablet in replica mode","messagePattern":"type PRIMARY cannot restore from backup, if you really need to do this, restart vttablet in replica mode","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vttablet/tabletmanager/rpc_backup.go","lineNumber":220,"sourceCode":"\tdefer func() {\n\t\tif startTime.IsZero() {\n\t\t\treturn\n\t\t}\n\t\ttm.QueryServiceControl.BroadcastHealth()\n\t\ttm.invokeRestoreDoneHook(startTime, restoreErr, backupEngine)\n\t}()\n\n\tif err := tm.lock(ctx); err != nil {\n\t\treturn err\n\t}\n\tdefer tm.unlock()\n\n\ttablet, err := tm.TopoServer.GetTablet(ctx, tm.tabletAlias)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif tablet.Type == topodatapb.TabletType_PRIMARY {\n\t\treturn errors.New(\"type PRIMARY cannot restore from backup, if you really need to do this, restart vttablet in replica mode\")\n\t}\n\n\t// Create the logger: tee to console and source.\n\tl := logutil.NewTeeLogger(logutil.NewConsoleLogger(), logger)\n\n\t// Now we can run restore.\n\tstartTime = time.Now()\n\tbackupEngine, restoreErr = tm.restoreBackupLocked(ctx, l, 0 /* waitForBackupInterval */, true /* deleteBeforeRestore */, request, mysqlShutdownTimeout)\n\n\treturn restoreErr\n}\n\nfunc (tm *TabletManager) IsBackupRunning() bool {\n\treturn tm._isBackupRunning\n}\n\nfunc (tm *TabletManager) beginBackup(backupMode string) error {\n\ttm.mutex.Lock()","sourceCodeStart":202,"sourceCodeEnd":238,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vttablet/tabletmanager/rpc_backup.go#L202-L238","documentation":"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.","triggerScenarios":"Calling RestoreFromBackup (vtctldclient RestoreFromBackup) against a tablet whose topo record has Type PRIMARY.","commonSituations":"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.","solutions":["Demote/remove the tablet from primary duty (reparent to another tablet) first","Restart vttablet in REPLICA type (edit the type in topo or start with the appropriate type) and then run the restore","Verify with vtctldclient GetTablets that the target is no longer PRIMARY before restoring"],"exampleFix":"// before\nvtctldclient RestoreFromBackup alias-1  # alias-1 is PRIMARY\n// after\nvtctldclient PlannedReparentShard ks -new-primary alias-2\n# restart alias-1 as replica, then:\nvtctldclient RestoreFromBackup alias-1","handlingStrategy":"validation","validationCode":"tablet, err := ts.GetTablet(ctx, alias)\nif err != nil { return err }\nif tablet.Type == topodatapb.TabletType_PRIMARY {\n    return fmt.Errorf(\"cannot restore %s: demote/restart as replica first\", topoproto.TabletAliasString(alias))\n}","typeGuard":null,"tryCatchPattern":"err := tm.RestoreFromBackup(ctx, logger)\nif err != nil && strings.Contains(err.Error(), \"cannot restore from backup\") {\n    return fmt.Errorf(\"tablet is PRIMARY in topo; reparent then restart as replica before restore\")\n}","preventionTips":["Gate restore automation on a non-PRIMARY topo type check","Include tablet type in restore runbooks and preflight checks","After emergency promotion, rebuild old primaries as replicas before any restore"],"tags":["vttablet","restore","primary","safety-check"],"backgroundTag":"restore-on-primary-not-allowed","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}