wavetermdev/waveterm · error
failed to read backup metadata: %w
Error message
failed to read backup metadata: %w
What it means
RestoreBackup derives the metadata sidecar path by replacing the .bak suffix with .json and reads it. This error wraps os.ReadFile failing on that .json file; without metadata (full path and permissions) the restore cannot proceed safely.
Source
Thrown at pkg/filebackup/filebackup.go:99
err = os.WriteFile(metadataPath, metadataJSON, 0600)
if err != nil {
return "", fmt.Errorf("failed to write backup metadata: %w", err)
}
return backupPath, nil
}
func RestoreBackup(backupFilePath string, restoreToFileName string) error {
backupData, err := os.ReadFile(backupFilePath)
if err != nil {
return fmt.Errorf("failed to read backup file: %w", err)
}
metadataPath := backupFilePath[:len(backupFilePath)-4] + ".json"
metadataData, err := os.ReadFile(metadataPath)
if err != nil {
return fmt.Errorf("failed to read backup metadata: %w", err)
}
var metadata BackupMetadata
err = json.Unmarshal(metadataData, &metadata)
if err != nil {
return fmt.Errorf("failed to unmarshal backup metadata: %w", err)
}
if metadata.FullPath != restoreToFileName {
return fmt.Errorf("backup metadata mismatch: expected %s, got %s", restoreToFileName, metadata.FullPath)
}
var perm os.FileMode
_, err = fmt.Sscanf(metadata.Perm, "%o", &perm)
if err != nil {
return fmt.Errorf("failed to parse file permissions: %w", err)
}
View on GitHub (pinned to a4447c1563)
Solutions
- Verify the .json sidecar exists next to the .bak file (same base name) before restoring.
- If the sidecar is gone, locate another backup of the same file in the dated directories that has both .bak and .json.
- Avoid copying/moving .bak files without their .json sidecars.
- Check cleanup scripts or manual deletions that remove .json files independently.
Example fix
// before os.Remove(backupPath + ".json") // 'cleanup' breaks restore // after // keep .bak and .json together: remove by shared base name os.Remove(strings.TrimSuffix(backupPath, ".bak") + ".json") // only when removing both
Defensive patterns
Strategy: validation
Validate before calling
metaPath := strings.TrimSuffix(backupFilePath, ".bak") + ".json"
if _, err := os.Stat(metaPath); err != nil {
return fmt.Errorf("metadata sidecar %s missing; backup pair incomplete", metaPath)
} Try / catch
err := filebackup.RestoreBackup(backupPath, targetPath)
if err != nil {
if strings.Contains(err.Error(), "read backup metadata") {
return fmt.Errorf("backup pair incomplete (.json sidecar missing): %w", err)
}
return err
} Prevention
- Always treat .bak and .json as an atomic pair
- Skip custom cleanup rules that single out .json files
- Check for half-failed backups (orphan .bak) after disk-full events
- Verify the sidecar exists before offering restore to users
When it happens
Trigger: The paired <name>.<hash>.<uuid>.json file is missing (deleted individually, partial backup from error 703 scenario, or a .bak file passed without its sidecar ever having been written).
Common situations: A prior backup half-failed leaving an orphan .bak; users or cleanup scripts deleting *.json files; restoring a .bak copied elsewhere without its sidecar.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- accessing file %s: %w
- file does not exist: %q
- cannot access image file: %v
- failed to unmarshal backup metadata: %w
- failed to parse file permissions: %w
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/f5ccc71000df6e00.
Report an issue: GitHub.