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

  1. Check permissions on the remote dir and chown/chmod it so the process user can write (dir is created with 0700)
  2. Verify the target path is not an existing directory: `ls -la` the parent dir for the offending name
  3. Remount the destination read-write if it is a read-only mount
  4. 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

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


AI-assisted analysis of VictoriaMetrics/VictoriaMetrics@5079fb58f1 (2026-09-03). Data as JSON: /api/errors/b093e04b0ebefa8b. Report an issue: GitHub.