kubernetes/kops · error

error during file write of %q: rename failed: %v

Error message

error during file write of %q: rename failed: %v

What it means

WriteFile stages data in a temp file and then atomically moves it into place with os.Rename(tempfile, p.location). This error is thrown when the rename fails — typically the temp file and target are on different filesystems/mounts, or the target directory's permissions changed. At this point the data was written and closed, but the final file was not updated.

Source

Thrown at util/pkg/vfs/fs.go:78

	f, err := os.CreateTemp(dir, "tmp")
	if err != nil {
		return fmt.Errorf("error creating temp file in %q: %v", dir, err)
	}

	// Note from here on in we have to close f and delete or rename the temp file
	tempfile := f.Name()

	_, err = io.Copy(f, data)

	if closeErr := f.Close(); err == nil {
		err = closeErr
	}

	if err == nil {
		err = os.Rename(tempfile, p.location)
		if err != nil {
			err = fmt.Errorf("error during file write of %q: rename failed: %v", p.location, err)
		}
	}

	if err == nil {
		return nil
	}

	// Something went wrong; try to remove the temp file
	if removeErr := os.Remove(tempfile); removeErr != nil {
		klog.Warningf("unable to remove temp file %q: %v", tempfile, removeErr)
	}

	return err
}

// To prevent concurrent creates on the same file while maintaining atomicity of writes,
// we take a process-wide lock during the operation.
// Not a great approach, but fine for a single process (with low concurrency)

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Ensure p.location is a file path, not an existing directory, and its parent is writable.
  2. Verify the temp file and target reside on the same filesystem (no mount point inserted between them).
  3. Check directory permissions/immutable flags (lsattr) and remove the immutable bit if set.
  4. Re-run the write; rename is atomic and a transient mount change is the usual culprit.

Example fix

// before
FSPath{location: "/srv/state/cluster"} // cluster exists as a directory -> rename fails
// after
FSPath{location: "/srv/state/cluster/spec.yaml"}
Defensive patterns

Strategy: try-catch

Validate before calling

if fi, err := os.Stat(target); err == nil && fi.IsDir() {
    return fmt.Errorf("target %s is a directory; rename would fail", target)
}
// same-filesystem check for the staging directory
if err := sameFilesystem(filepath.Dir(target), filepath.Dir(target)); err != nil {
    return err
}

Try / catch

if err := p.WriteFile(ctx, data, acl); err != nil && strings.Contains(err.Error(), "rename failed") {
    if errors.Is(errors.Unwrap(errors.Unwrap(err)), syscall.EXDEV) {
        return fmt.Errorf("temp file and target are on different filesystems: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling CreateFile/WriteFile where os.Rename fails: target directory not writable (cannot replace/create the final name), p.location is a directory, or the temp dir and target are on different mount points after a bind mount/overlay change.

Common situations: p.location pointing at an existing directory instead of a file, the parent directory becoming read-only mid-write, container volume mounts making the temp file land on a different device than the target.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/517e870d33a82075. Report an issue: GitHub.