VictoriaMetrics/VictoriaMetrics · error
cannot read metadata from %s: %w
Error message
cannot read metadata from %s: %w
What it means
copyMetadata reads BackupMetadataFilename from the source remote FS before writing it to the destination. If that read fails, the copy is aborted with this error naming the source location. Without metadata, restoring the copied backup would lack required backup description, so the operation refuses to continue.
Source
Thrown at lib/backup/actions/copy.go:54
return fmt.Errorf("cannot delete `backup complete` file at %s: %w", dst, err)
}
if err := runCopy(src, dst, concurrency); err != nil {
return err
}
if err := copyMetadata(src, dst); err != nil {
return fmt.Errorf("cannot store backup metadata: %w", err)
}
if err := dst.CreateFile(backupnames.BackupCompleteFilename, nil); err != nil {
return fmt.Errorf("cannot create `backup complete` file at %s: %w", dst, err)
}
return nil
}
func copyMetadata(src common.RemoteFS, dst common.RemoteFS) error {
metadata, err := src.ReadFile(backupnames.BackupMetadataFilename)
if err != nil {
return fmt.Errorf("cannot read metadata from %s: %w", src, err)
}
if err := dst.CreateFile(backupnames.BackupMetadataFilename, metadata); err != nil {
return fmt.Errorf("cannot create metadata at %s: %w", dst, err)
}
return nil
}
func runCopy(src common.OriginFS, dst common.RemoteFS, concurrency int) error {
startTime := time.Now()
logger.Infof("starting remote backup copy from %s to %s", src, dst)
srcParts, err := src.ListParts()
if err != nil {
return fmt.Errorf("cannot list src parts: %w", err)
}
logger.Infof("obtained %d parts from src %s", len(srcParts), src)
View on GitHub (pinned to 5079fb58f1)
Solutions
- Confirm the source backup actually contains the metadata file (check bucket listing for the metadata object name)
- Check read permissions on the source bucket/prefix for the configured credentials
- If the source is a legacy backup without metadata, re-create the backup from the database instead of copying it
- Inspect the wrapped (%w) error to distinguish NotFound vs access-denied vs transient API failure
Example fix
// before: copy blindly
err := copyAction.Run()
// after: verify metadata exists first
ok, _ := src.HasFile(backupnames.BackupMetadataFilename)
if !ok {
log.Fatal("source backup has no metadata file; cannot copy")
}
err = copyAction.Run() Defensive patterns
Strategy: validation
Validate before calling
ok, err := src.HasFile(backupnames.BackupMetadataFilename)
if err != nil {
return fmt.Errorf("cannot probe source metadata: %w", err)
}
if !ok {
return errors.New("source backup has no metadata file; re-create the backup")
} Try / catch
if err := copyAction.Run(); err != nil {
if strings.Contains(err.Error(), "cannot read metadata") {
log.Printf("source metadata unreadable: %v", err) // check perms / legacy backup
}
} Prevention
- Confirm source backups are created by a version that writes metadata
- Grant read/list permission on the source bucket/prefix
- Never manually delete metadata objects from source backups
When it happens
Trigger: RemoteBackupCopy.Run -> copyMetadata when src.ReadFile(backupnames.BackupMetadataFilename) returns an error: file missing in source, read access denied, or storage API failure.
Common situations: Backing up from a legacy/old backup that predates metadata files; source bucket credentials lacking read access; source backup truncated or manually deleted metadata object.
Related errors
- cannot store backup metadata: %w
- cannot create metadata at %s: %w
- cannot store backup metadata: %w
- cannot remove empty directories at %s: %w
- cannot copy %s from %s to %s: %w
AI-assisted analysis of VictoriaMetrics/VictoriaMetrics@5079fb58f1 (2026-09-03).
Data as JSON: /api/errors/f34ab905fc1ee471.
Report an issue: GitHub.