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

  1. Take the backup from a replica or rdonly tablet instead
  2. If truly backing up the primary, pass --allow-primary to the backup command
  3. 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

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


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