wavetermdev/waveterm · error

failed to restore file: %w

Error message

failed to restore file: %w

What it means

RestoreBackup's final step writes the backed-up contents back to restoreToFileName with the recorded permissions via os.WriteFile. This error wraps that write failing; the restore did not complete and the target file may be left unchanged or (if newly created) partially written.

Source

Thrown at pkg/filebackup/filebackup.go:120

	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)
	}

	err = os.WriteFile(restoreToFileName, backupData, perm)
	if err != nil {
		return fmt.Errorf("failed to restore file: %w", err)
	}

	return nil
}

func CleanupOldBackups() error {
	backupBaseDir := filepath.Join(wavebase.GetWaveCachesDir(), "waveai-backups")

	if _, err := os.Stat(backupBaseDir); os.IsNotExist(err) {
		return nil
	}

	entries, err := os.ReadDir(backupBaseDir)
	if err != nil {
		return fmt.Errorf("failed to read backup directory: %w", err)
	}

	cutoffTime := time.Now().Add(-BackupRetentionPeriod)

View on GitHub (pinned to a4447c1563)

Solutions

  1. Close any process holding the target file open and retry the restore.
  2. Check write permissions on the target file and its containing directory (and that the target is a file, not a directory).
  3. Free disk space / check quota on the target filesystem.
  4. If the directory is read-only, restore to a writable location by copying the .bak manually, or fix mount permissions.

Example fix

// before
chmod 444 notes.txt && restore  # WriteFile fails: permission denied
// after
chmod 644 notes.txt  # or restore, then re-apply perms (restore sets perm itself)
Defensive patterns

Strategy: try-catch

Validate before calling

if fi, err := os.Stat(restoreTo); err == nil && fi.IsDir() {
    return fmt.Errorf("restore target %s is a directory", restoreTo)
}
if dir := filepath.Dir(restoreTo); !writable(dir) {
    return fmt.Errorf("directory %s not writable", dir)
}

Try / catch

err := filebackup.RestoreBackup(backupPath, targetPath)
if err != nil {
    var perr *fs.PathError
    if errors.As(err, &perr) && (errors.Is(perr.Err, syscall.EACCES) || errors.Is(perr.Err, syscall.EBUSY)) {
        return fmt.Errorf("close programs using %s or fix permissions, then retry: %w", targetPath, err)
    }
    return err
}

Prevention

When it happens

Trigger: os.WriteFile(restoreToFileName, backupData, perm) fails: target directory unwritable, file locked by another process, read-only filesystem, disk full, or the target path is a directory.

Common situations: File open in an editor/another process with a write lock (common on Windows); project directory made read-only; the original file was deleted and its directory is no longer writable; disk quota exhausted.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/2045013c209e7a9d. Report an issue: GitHub.