kubernetes/kops · error

renaming file %q -> %q (with %q): %w

Error message

renaming file %q -> %q (with %q): %w

What it means

The non-posix fallback renames the temp file by running a shell command (`mv tempfile p.path`, prefixed with `sudo` if p.sudo is set) through session.Run. If the command exits non-zero, this error wraps the failure and includes the exact command executed. Causes include permission denied, missing mv, or remote disk issues.

Source

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

		}
		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
		}
		if err := session.Run(cmd); err != nil {
			return fmt.Errorf("renaming file %q -> %q (with %q): %w", tempfile, p.path, cmd, err)
		}
		deleteTempFile = false
	}

	return nil
}

// 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)
var createFileLockSSH sync.Mutex

func (p *SSHPath) CreateFile(ctx context.Context, data io.ReadSeeker, acl ACL) error {
	createFileLockSSH.Lock()
	defer createFileLockSSH.Unlock()

	// Check if exists
	_, err := p.ReadFile(ctx)

View on GitHub (pinned to 4c8573c808)

Solutions

  1. If permission is the issue, construct the SSHPath with sudo enabled: vfs.NewSSHPath(client, server, path, true), and ensure the user has passwordless sudo for mv (NOPASSWD in sudoers).
  2. Remove 'requiretty' and any password prompt for the automation user in /etc/sudoers so non-interactive `sudo mv` works.
  3. Manually test the exact command from the error message via SSH to see the underlying output.
  4. Verify `mv` exists in the default PATH for non-interactive sessions; use an absolute path (/bin/mv) if the PATH is minimal.

Example fix

// before: sudoers prompts for password, session.Run fails
sftpuser ALL=(ALL) ALL
// after
sftpuser ALL=(ALL) NOPASSWD: /bin/mv
Defensive patterns

Strategy: validation

Validate before calling

// confirm passwordless sudo mv works non-interactively before relying on it
out := sshRun(host, "sudo -n true && echo sudo-ok")
// require "sudo-ok"

Try / catch

err := path.WriteFile(ctx, data, acl)
if err != nil && strings.Contains(err.Error(), "renaming file") {
    return fmt.Errorf("remote mv failed; run the quoted command manually via ssh to see the real output: %w", err)
}

Prevention

When it happens

Trigger: session.Run("mv ...") returns non-zero: the SSH user lacks permission on either path (and p.sudo is false so no sudo was used), sudo requires a password/TTY, the shell is restricted, or the target directory vanished.

Common situations: Writing to root-owned directories without sudo on the SSHPath; sudoers requiring a TTY (requiretty) or password for the automation user; restricted rbash on bastion hosts; read-only root filesystem.

Related errors


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