vitessio/vitess · error
AddFile cannot be called on read-only backup
Error message
AddFile cannot be called on read-only backup
What it means
GCSBackupHandle.AddFile rejects writes to a backup handle opened read-only. Read-only handles represent backups opened for inspection or restore; adding files to them is not permitted and returns this error. It enforces that backup contents are immutable once a backup is finalized.
Source
Thrown at go/vt/mysqlctl/gcsbackupstorage/gcs.go:86
name string
readOnly bool
mysqlctlerrors.PerFileErrorRecorder
}
// Directory implements BackupHandle.
func (bh *GCSBackupHandle) Directory() string {
return bh.dir
}
// Name implements BackupHandle.
func (bh *GCSBackupHandle) Name() string {
return bh.name
}
// AddFile implements BackupHandle.
func (bh *GCSBackupHandle) AddFile(ctx context.Context, filename string, filesize int64) (io.WriteCloser, error) {
if bh.readOnly {
return nil, errors.New("AddFile cannot be called on read-only backup")
}
object := objName(bh.dir, bh.name, filename)
return bh.client.Bucket(bucket).Object(object).NewWriter(ctx), nil
}
// Wait implements BackupHandle.
func (bh *GCSBackupHandle) Wait() {}
// EndBackup implements BackupHandle.
func (bh *GCSBackupHandle) EndBackup(ctx context.Context) error {
if bh.readOnly {
return errors.New("EndBackup cannot be called on read-only backup")
}
return nil
}
// AbortBackup implements BackupHandle.
func (bh *GCSBackupHandle) AbortBackup(ctx context.Context) error {View on GitHub (pinned to 01a25a7d17)
Solutions
- Use a read-write handle (StartBackup/CreateBackup path) when you need AddFile
- Do not call AddFile on existing backups; create a new backup instead of mutating a finished one
- Check the handle's readOnly flag before branching into write calls
Example fix
// before bh := bs.StartBackup(ctx, dir, name, true /* readOnly */) w, err := bh.AddFile(ctx, "binlog.pos", 64) // error // after bh := bs.StartBackup(ctx, dir, name, false) w, err := bh.AddFile(ctx, "binlog.pos", 64)
Defensive patterns
Strategy: validation
Validate before calling
if bh.readOnly {
return errors.New("cannot AddFile on a read-only GCS backup handle")
}
w, err := bh.AddFile(ctx, filename, filesize) Try / catch
w, err := bh.AddFile(ctx, filename, size)
if err != nil {
if strings.Contains(err.Error(), "AddFile cannot be called on read-only backup") {
return fmt.Errorf("%w: reopen the backup for writing", err)
}
return err
} Prevention
- Only request write handles when creating a new backup
- Never mutate finalized backups; create a new backup instead
- Branch write calls on the handle's readOnly mode
When it happens
Trigger: Calling AddFile on a GCSBackupHandle created with readOnly=true (typical of restore/verification flows that open existing GCS backups read-only).
Common situations: Backup-verification or restore code accidentally invoking the write path; sharing a handle between a read pass and a write pass; copying logic written for a fresh-backup handle onto a read-only handle.
Related errors
- EndBackup cannot be called on read-only backup
- AbortBackup cannot be called on read-only backup
- ReadFile cannot be called on read-write backup
- ReadFile cannot be called on read-write backup
- lock already acquired
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/4ce44ee0a62273df.
Report an issue: GitHub.