kubernetes/kops · error

error creating sftp client: %w

Error message

error creating sftp client: %w

What it means

SSHPath.newClient in util/pkg/vfs/sshfs.go wraps the error from sftp.NewClient(p.client) with this message when the non-sudo path tries to open an SFTP subsystem over an established SSH connection. It means the SSH connection succeeded but the SFTP subsystem could not be initialized — almost always because the remote host does not expose an sftp subsystem or the server rejected the subsystem request. All SSHPath file operations (Remove, WriteFile, WriteTo, ReadDir, ReadTree) go through this.

Source

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

	Mode os.FileMode
}

var _ Path = &SSHPath{}

func NewSSHPath(client *ssh.Client, server string, path string, sudo bool) *SSHPath {
	return &SSHPath{
		client: client,
		server: server,
		path:   path,
		sudo:   sudo,
	}
}

func (p *SSHPath) newClient(ctx context.Context) (*sftp.Client, error) {
	if !p.sudo {
		sftpClient, err := sftp.NewClient(p.client)
		if err != nil {
			return nil, fmt.Errorf("error creating sftp client: %w", err)
		}

		return sftpClient, nil
	}
	s, err := p.client.NewSession()
	if err != nil {
		return nil, fmt.Errorf("error creating sftp client (in new-session): %w", err)
	}

	stdin, err := s.StdinPipe()
	if err != nil {
		return nil, fmt.Errorf("error creating sftp client (at stdin pipe): %w", err)
	}
	stdout, err := s.StdoutPipe()
	if err != nil {
		return nil, fmt.Errorf("error creating sftp client (at stdout pipe): %w", err)
	}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Ensure the remote sshd_config contains `Subsystem sftp /usr/lib/openssh/sftp-server` (or equivalent) and restart sshd
  2. Install/verify the sftp-server binary on the remote host
  3. Re-establish the ssh.Client if the connection may have gone stale, then retry
  4. As a workaround, use NewSSHPath with sudo=true so the client runs `sudo sftp-server` over a session instead of the subsystem
  5. Check server logs (/var/log/auth.log) for subsystem or MaxSessions denials

Example fix

// before (server sshd_config without sftp subsystem)
# Subsystem sftp /usr/lib/openssh/sftp-server
// after
Subsystem sftp internal-sftp
# then: sudo systemctl restart sshd
Defensive patterns

Strategy: retry

Validate before calling

// probe the sftp subsystem before using the VFS path
session, err := client.NewSession()
if err == nil {
	defer session.Close()
	out, err := session.CombinedOutput("/usr/lib/openssh/sftp-server -v 2>&1 | head -1 || which sftp-server")
	_ = out
	if err != nil { log.Printf("warning: sftp-server not found on host: %v", err) }
}

Type guard

func isSFTPSubsystemError(err error) bool {
	return err != nil && strings.Contains(err.Error(), "error creating sftp client") &&
		!strings.Contains(err.Error(), "new-session")
}

Try / catch

sftpClient, err := path.(*vfs.SSHPath) // operations are on the path itself
if err := p.Remove(ctx); err != nil {
	if strings.Contains(err.Error(), "error creating sftp client") {
		// retry once with a fresh ssh.Client
		client, derr := ssh.Dial("tcp", host, cfg)
		if derr == nil {
			p = vfs.NewSSHPath(client, host, path, sudo)
			return p.Remove(ctx)
		}
	}
	return err
}

Prevention

When it happens

Trigger: Any SSHPath operation where sudo=false and sftp.NewClient fails: the remote sshd has no `Subsystem sftp ...` line, the sftp-server binary is missing, MaxSessions/subsystem restrictions apply, or the SSH connection has already been closed by the server.

Common situations: Using an ssh:// VFS state store against a hardened/locked-down sshd (e.g. minimal containers, restricted ForceCommand); connecting to hosts without openssh-sftp-server installed; stale ssh.Client after network interruption or server timeout.

Related errors


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