vitessio/vitess · error
type PRIMARY cannot take backup. if you really need to do th
Error message
type PRIMARY cannot take backup. if you really need to do this, rerun the backup command with --allow-primary
What it means
Backups are normally taken from replica/rdonly tablets; taking one from the current PRIMARY is disallowed unless explicitly permitted. The in-process tablet type is PRIMARY and the request did not set AllowPrimary. This check exists because a network partition can make the topo think a tablet demoted while the process still believes it is primary.
Source
Thrown at go/vt/vttablet/tabletmanager/rpc_backup.go:57
const (
backupModeOnline = "online"
backupModeOffline = "offline"
)
// Backup takes a db backup and sends it to the BackupStorage.
func (tm *TabletManager) Backup(ctx context.Context, logger logutil.Logger, req *tabletmanagerdatapb.BackupRequest) error {
if tm.Cnf == nil {
return errors.New("cannot perform backup without my.cnf, please restart vttablet with a my.cnf file specified")
}
// Check tablet type current process has.
// During a network partition it is possible that from the topology perspective this is no longer the primary,
// but the process didn't find out about this.
// It is not safe to take backups from tablet in this state
currentTablet := tm.Tablet()
if !req.AllowPrimary && currentTablet.Type == topodatapb.TabletType_PRIMARY {
return errors.New("type PRIMARY cannot take backup. if you really need to do this, rerun the backup command with --allow-primary")
}
backupEngine := ""
if req.BackupEngine != nil {
backupEngine = *req.BackupEngine
}
engine, err := mysqlctl.GetBackupEngine(backupEngine)
if err != nil {
return vterrors.Wrap(err, "failed to find backup engine")
}
// Get Tablet info from topo so that it is up to date
tablet, err := tm.TopoServer.GetTablet(ctx, tm.tabletAlias)
if err != nil {
return err
}
if !req.AllowPrimary && tablet.Type == topodatapb.TabletType_PRIMARY {
return errors.New("type PRIMARY cannot take backup. if you really need to do this, rerun the backup command with --allow-primary")View on GitHub (pinned to 01a25a7d17)
Solutions
- Take the backup from a replica or rdonly tablet instead
- If truly backing up the primary, pass --allow-primary to the backup command
- Verify tablet types via vtctldclient GetTablets before scheduling backups
Example fix
// before vtctldclient Backup alias-1 # alias-1 is PRIMARY // after vtctldclient Backup --allow-primary alias-1 # or target a replica
Defensive patterns
Strategy: validation
Validate before calling
tablets, err := ts.GetTabletsByType(ctx, keyspace, topodatapb.TabletType_REPLICA)
if err != nil { return err }
if len(tablets) == 0 { return errors.New("no replica available for backup") }
backupTarget := tablets[0] // never schedule backups against PRIMARY Try / catch
err := tm.Backup(ctx, logger, req)
if err != nil && strings.Contains(err.Error(), "--allow-primary") {
return fmt.Errorf("refusing backup of PRIMARY %s; target a replica", alias)
} Prevention
- Select backup targets by current topo type, not static aliases
- Filter out PRIMARY tablets in backup scheduling code
- Only pass --allow-primary deliberately and with operator sign-off
When it happens
Trigger: Running vtctldclient Backup against a tablet whose current tm.Tablet().Type is PRIMARY without --allow-primary.
Common situations: Operator targets the wrong tablet alias; scripted backups picking the primary by mistake; split-brain scenarios where a deposed primary still reports PRIMARY locally.
Related errors
- type PRIMARY cannot restore from backup, if you really need
- cannot perform backup without my.cnf, please restart vttable
- mysqld >= 8.0.21 required to disable the redo log
- ErrPartSize
- AddFile cannot be called on read-only backup
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/daa66d6b1d6f2dc4.
Report an issue: GitHub.