wavetermdev/waveterm · error
failed to read file for backup: %w
Error message
failed to read file for backup: %w
What it means
After successfully statting the file, MakeFileBackup reads its full contents with os.ReadFile to store the snapshot. If the read fails — file deleted in the race window between Stat and Read, permission denied, or an I/O error — this wrapped error is returned and the edit/delete is aborted.
Source
Thrown at pkg/filebackup/filebackup.go:36
)
const BackupRetentionPeriod = 5 * 24 * time.Hour
type BackupMetadata struct {
FullPath string `json:"fullpath"`
Timestamp string `json:"timestamp"`
Perm string `json:"perm"`
}
func MakeFileBackup(absFilePath string) (string, error) {
fileInfo, err := os.Stat(absFilePath)
if err != nil {
return "", fmt.Errorf("failed to stat file for backup: %w", err)
}
fileData, err := os.ReadFile(absFilePath)
if err != nil {
return "", fmt.Errorf("failed to read file for backup: %w", err)
}
dir := filepath.Dir(absFilePath)
basename := filepath.Base(absFilePath)
hash := sha256.Sum256([]byte(dir))
dirHash8 := hex.EncodeToString(hash[:])[:8]
uuidV7, err := uuid.NewV7()
if err != nil {
return "", fmt.Errorf("failed to generate UUID: %w", err)
}
uuidStr := uuidV7.String()
now := time.Now()
dateStr := now.Format("2006-01-02")
backupDir := filepath.Join(wavebase.GetWaveCachesDir(), "waveai-backups", dateStr)View on GitHub (pinned to a4447c1563)
Solutions
- Retry the operation — a transient race usually succeeds on a second attempt
- Verify read permission on the file (and search permission on parent dirs)
- Check filesystem health/disk errors in system logs if I/O errors repeat
- Re-open/refresh the file in Wave so it operates on the current state
Example fix
// before
fileData, err := os.ReadFile(absFilePath)
if err != nil { return "", fmt.Errorf("failed to read file for backup: %w", err) }
// after
fileData, err := os.ReadFile(absFilePath)
if os.IsNotExist(err) {
return "", fmt.Errorf("file vanished between stat and read: %w", err) // caller can treat as deleted
} Defensive patterns
Strategy: retry
Validate before calling
info, err := os.Stat(absFilePath)
if err == nil && info.Mode().Perm()&0o400 == 0 {
return fmt.Errorf("file is not readable: %s", absFilePath)
} Try / catch
backupPath, err := filebackup.MakeFileBackup(path)
if err != nil {
if errors.Is(errors.Unwrap(err), os.IsPermission(nil)) || os.IsPermission(errors.Unwrap(err)) {
return fmt.Errorf("cannot back up unreadable file: %w", err)
}
// transient race: retry once
backupPath, err = filebackup.MakeFileBackup(path)
} Prevention
- Retry once on failure — Stat/Read TOCTOU races are usually transient
- Verify read permission (and that the file is a regular file, not /dev/null or a fifo)
- Avoid editing files on flaky network mounts when possible
- Re-open the file in Wave after external modifications to refresh state
When it happens
Trigger: os.ReadFile(absFilePath) fails after os.Stat succeeded: TOCTOU deletion, read permission missing, or disk I/O error.
Common situations: Another process deletes/truncates the file between Stat and Read; read-protected files (chmod 000) or root-owned files edited by non-root Wave; NFS/network filesystem hiccups.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- failed to stat file for backup: %w
- failed to create backup directory: %w
- failed to write backup file: %w
- failed to write backup metadata: %w
- failed to get app directory: %w
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/f8ff16dddbfc7d1c.
Report an issue: GitHub.