kubernetes/kops · error

renaming file -> (with )

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.

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.

Appendix: 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)