vitessio/vitess · error
ReadFile cannot be called on read-write backup
Error message
ReadFile cannot be called on read-write backup
What it means
GCSBackupHandle.ReadFile requires a read-only handle; it is the mirror guard of AddFile's. Reads are only permitted on handles opened read-only so that restore/inspection traffic can be distinguished from backup writing, and a read-write handle cannot be used to stream files back.
Source
Thrown at go/vt/mysqlctl/gcsbackupstorage/gcs.go:114
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 {
if bh.readOnly {
return errors.New("AbortBackup cannot be called on read-only backup")
}
return bh.bs.RemoveBackup(ctx, bh.dir, bh.name)
}
// ReadFile implements BackupHandle.
func (bh *GCSBackupHandle) ReadFile(ctx context.Context, filename string) (io.ReadCloser, error) {
if !bh.readOnly {
return nil, errors.New("ReadFile cannot be called on read-write backup")
}
object := objName(bh.dir, bh.name, filename)
return bh.client.Bucket(bucket).Object(object).NewReader(ctx)
}
// GCSBackupStorage implements BackupStorage for Google Cloud Storage.
type GCSBackupStorage struct {
// client is the instance of the Google Cloud Storage Go client.
// Once this field is set, it must not be written again/unset to nil.
_client *storage.Client
// mu guards all fields.
mu sync.Mutex
}
// ListBackups implements BackupStorage.
func (bs *GCSBackupStorage) ListBackups(ctx context.Context, dir string) ([]backupstorage.BackupHandle, error) {
c, err := bs.client(ctx)
if err != nil {View on GitHub (pinned to 01a25a7d17)
Solutions
- Open a second handle with readOnly=true for any ReadFile calls
- Complete the write phase, then re-open the backup read-only to verify contents
- Check the handle's readOnly mode before dispatching read vs write operations
Example fix
// before bh := bs.StartBackup(ctx, dir, name, false) r, err := bh.ReadFile(ctx, "backupinfo") // error // after rh := bs.StartBackup(ctx, dir, name, true /* readOnly */) r, err := rh.ReadFile(ctx, "backupinfo")
Defensive patterns
Strategy: validation
Validate before calling
if bh.readOnly == false {
return errors.New("ReadFile requires a read-only handle; re-open the backup read-only")
}
r, err := bh.ReadFile(ctx, filename) Try / catch
r, err := bh.ReadFile(ctx, filename)
if err != nil {
if strings.Contains(err.Error(), "ReadFile cannot be called on read-write backup") {
// obtain a readOnly handle and retry
}
return err
} Prevention
- Verify backup contents via a separate read-only handle after the write phase completes
- Keep verification helpers taking read-only handles only
When it happens
Trigger: Calling ReadFile on a GCSBackupHandle created for backup writing (readOnly=false, e.g. from StartBackup with readOnly=false).
Common situations: Verification code that opens a handle to write and then tries to read back what it wrote; generic helper functions assuming one handle serves both directions.
Related errors
- AddFile cannot be called on read-only backup
- EndBackup cannot be called on read-only backup
- AbortBackup cannot be called on read-only 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/9e56d783c4d03969.
Report an issue: GitHub.