VictoriaMetrics/VictoriaMetrics · error
cannot create file %q: %w
Error message
cannot create file %q: %w
What it means
UploadPart creates the destination part file with os.Create after ensuring its parent directory exists. This error wraps any failure from os.Create — most commonly permission denied on the target directory, or the path is a directory / read-only filesystem. It is thrown before any bytes are copied.
Source
Thrown at lib/backup/fsremote/fsremote.go:168
}
if err != nil {
return fmt.Errorf("cannot download data from %q: %w", path, err)
}
if uint64(n) != p.Size {
return fmt.Errorf("wrong data size downloaded from %q; got %d bytes; want %d bytes", path, n, p.Size)
}
return nil
}
// UploadPart uploads p from r to fs.
func (fs *FS) UploadPart(p common.Part, r io.Reader) error {
path := fs.path(p)
if err := fs.mkdirAll(path); err != nil {
return err
}
w, err := os.Create(path)
if err != nil {
return fmt.Errorf("cannot create file %q: %w", path, err)
}
n, err := io.Copy(w, r)
if err := w.Sync(); err != nil {
return fmt.Errorf("cannot fsync file: %q: %w", w.Name(), err)
}
if err1 := w.Close(); err1 != nil && err == nil {
err = err1
}
if err != nil {
_ = os.RemoveAll(path)
return fmt.Errorf("cannot upload data to %q: %w", path, err)
}
if uint64(n) != p.Size {
_ = os.RemoveAll(path)
return fmt.Errorf("wrong data size uploaded to %q; got %d bytes; want %d bytes", path, n, p.Size)
}
return nil
}View on GitHub (pinned to 5079fb58f1)
Solutions
- Check permissions on the remote dir and chown/chmod it so the process user can write (dir is created with 0700)
- Verify the target path is not an existing directory: `ls -la` the parent dir for the offending name
- Remount the destination read-write if it is a read-only mount
- Check container security contexts / SELinux denials (audit2allow, `dmesg`)
Example fix
// before: dir created by root, process runs as non-root sudo mkdir -p /backups/vm && sudo chmod 755 /backups/vm // after: give the backup user ownership sudo chown -R vmbackup:vmbackup /backups/vm && sudo chmod 700 /backups/vm
Defensive patterns
Strategy: validation
Validate before calling
import "os"
func ensureRemoteWritable(dir string) error {
if info, err := os.Stat(dir); err != nil {
return err
} else if !info.IsDir() {
return fmt.Errorf("%s is not a directory", dir)
}
probe := filepath.Join(dir, ".write-probe")
if err := os.WriteFile(probe, []byte("ok"), 0600); err != nil {
return fmt.Errorf("remote dir %s not writable: %w", dir, err)
}
return os.Remove(probe)
} Try / catch
err := fsRemote.UploadPart(part, r)
if errors.Is(err, os.ErrPermission) {
// fix ownership/permissions of remote dir or run as correct user
} else if err != nil {
return fmt.Errorf("upload failed: %w", err)
} Prevention
- Run the backup process as the same user that owns the remote dir (dir is created 0700)
- Check the destination is not a read-only mount before the backup starts
- Probe writability with a temp file as a pre-flight check
- Avoid placing remote dirs where part names may collide with existing paths
When it happens
Trigger: Calling UploadPart when the remote dir path exists but is not writable by the process user, a file/symlink already exists at the target path with restrictive permissions, the target name collides with an existing directory, or the underlying filesystem is read-only (e.g. read-only mount).
Common situations: Backup destination mounted read-only (failed-over NFS/S3-fs mount); fsremote dir owned by a different user than the vmbackup process (container running as non-root vs dir created by root); path collision because a part filename was created as a directory by accident; SELinux/AppArmor denial.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- cannot delete `backup complete` file at %s: %w
- cannot list src parts: %w
- cannot create reader for %s from %s: %w
- cannot open directory: %w
- cannot append files %q: %w
AI-assisted analysis of VictoriaMetrics/VictoriaMetrics@5079fb58f1 (2026-09-03).
Data as JSON: /api/errors/b093e04b0ebefa8b.
Report an issue: GitHub.