kubernetes/kops · error

removing destination sftp file %q before rename: %w

Error message

removing destination sftp file %q before rename: %w

What it means

Because POSIX-rename via SFTP fails when the destination exists, WriteFile first removes the destination file p.path. If Remove fails with anything other than NotExist, this error wraps the cause. It means the old file could not be cleared, so the atomic rename was not attempted.

Source

Thrown at util/pkg/vfs/sshfs.go:240

		if !ok {
			return fmt.Errorf("unexpected acl type %T", acl)
		} else {
			err = sftpClient.Chmod(tempfile, sshACL.Mode)
			if err != nil {
				return fmt.Errorf("error during chmod of %q: %w", tempfile, err)
			}
		}
	}

	// posix rename will replace the destination (normal sftp rename does not)
	usePosixRename := true
	if usePosixRename {
		// posix rename fails if destination exists, try to delete just in case
		if err := sftpClient.Remove(p.path); err != nil {
			if os.IsNotExist(err) {
				// expected when file does not exist already
			} else {
				return fmt.Errorf("removing destination sftp file %q before rename: %w", p.path, err)
			}
		}
		if err := sftpClient.Rename(tempfile, p.path); err != nil {
			return fmt.Errorf("renaming sftp file %q -> %q (with posix rename): %w", tempfile, p.path, err)
		}
		deleteTempFile = false
	} else {
		var session *ssh.Session
		session, err = p.client.NewSession()
		if err != nil {
			return fmt.Errorf("creating session for rename: %w", err)
		}
		defer session.Close()

		cmd := "mv " + tempfile + " " + p.path
		if p.sudo {
			cmd = "sudo " + cmd
		}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. SSH to the host and remove/fix ownership of the destination: `sudo rm <path>` or `sudo chown <sftpuser> <dir>`.
  2. Grant the SFTP user write permission on the destination directory (directory write permission, not file ownership, is what Remove needs).
  3. Check for immutable flags: `lsattr <path>` and `sudo chattr -i <path>` if set.
  4. Retry if the wrapped error indicates a transient connection issue.

Example fix

// before: /etc/kubernetes/manifests owned by root, sftp user cannot delete
$ ssh host 'sudo chown -R sftpuser:sftpuser /etc/kubernetes/manifests'
// after: retry kops write — destination removal succeeds
Defensive patterns

Strategy: validation

Validate before calling

// destination removal needs write permission on the directory
out := sshRun(host, fmt.Sprintf("test -w %s && echo dir-writable", path.Dir(dest)))

Try / catch

err := path.WriteFile(ctx, data, acl)
if err != nil {
    var permErr *fs.PathError
    if strings.Contains(err.Error(), "removing destination sftp file") {
        // escalate ownership on the remote dir, then retry
        sshRun(host, fmt.Sprintf("sudo chown %s %s", sftpUser, path.Dir(dest)))
        return path.WriteFile(ctx, data, acl)
    }
    _ = permErr
    return err
}

Prevention

When it happens

Trigger: sftpClient.Remove(p.path) fails with EACCES/EPERM (no write permission on the directory containing the destination), EBUSY, or a connection error — i.e. the destination exists but cannot be deleted.

Common situations: Overwriting an existing file on a host where the SFTP user lacks directory write permission (file owned by root); destination directory has sticky bit and different owner; immutable attribute (chattr +i) on the file.

Related errors


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