vitessio/vitess · error
a backup is already running on tablet: %v
Error message
a backup is already running on tablet: %v
What it means
beginBackup enforces that only one backup runs at a time on a tablet, using the _isBackupRunning flag guarded by the tablet manager mutex. If a backup (online or offline) is already in progress, any new Backup RPC fails immediately with this error.
Source
Thrown at go/vt/vttablet/tabletmanager/rpc_backup.go:241
// 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()
defer tm.mutex.Unlock()
if tm._isBackupRunning {
return fmt.Errorf("a backup is already running on tablet: %v", tm.tabletAlias)
}
// When mode is online we don't take the action lock, so we continue to serve,
// but let's set _isBackupRunning to true.
// So that we only allow one online backup at a time.
// Offline backups also run only one at a time because we take the action lock
// so this is not really needed in that case, however we are using it to record the state
tm._isBackupRunning = true
statsBackupIsRunning.Set([]string{backupMode}, 1)
return nil
}
func (tm *TabletManager) endBackup(backupMode string) {
// Now we set _isBackupRunning back to false.
// Have to take the mutex lock before writing to _ fields.
tm.mutex.Lock()
defer tm.mutex.Unlock()
tm._isBackupRunning = false
statsBackupIsRunning.Set([]string{backupMode}, 0)View on GitHub (pinned to 01a25a7d17)
Solutions
- Wait for the running backup to complete (check vttablet logs for backup progress)
- Cancel or kill the stuck backup and its process, then retry
- Stagger scheduled backups so they do not overlap on the same tablet
- Restart vttablet if the backup process died and left the flag set (the in-memory flag is cleared on restart)
Defensive patterns
Strategy: retry
Validate before calling
// Guard: only start a backup when none is in flight on this tablet
if backupInFlight[alias] {
return fmt.Errorf("backup already scheduled for %s", alias)
} Try / catch
err := vtctldclientBackup(alias)
if err != nil && strings.Contains(err.Error(), "a backup is already running") {
time.Sleep(backoff)
return vtctldclientBackup(alias) // retry after the running backup finishes
} Prevention
- Schedule backups so they never overlap on the same tablet
- Check vttablet logs for an active backup before manual triggers
- Use exponential backoff on retries
- Alert on backups exceeding expected duration to catch hung ones
When it happens
Trigger: Calling vtctldclient Backup (or an automated backup schedule) on a tablet while a previous backup — including an online backup that does not take the action lock — is still running.
Common situations: Overlapping scheduled backups, a hung/slow backup still running when a manual backup is triggered, retry loops re-triggering Backup before the first attempt finished.
Related errors
- Tablet: %v, is already drained
- invalid choice for enum
- value must be either a float64 (interpreted as seconds) or a
- flagutil: NewOptionalFlag requires a non-nil parse function
- flagutil: OptionalFlagValue has no parse function; use a con
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/89e0f4c0a5559080.
Report an issue: GitHub.