{"record":{"id":"1f5d9b0ad89933de","repo":"kubernetes/kops","slug":"error-creating-sftp-client-w","errorCode":null,"errorMessage":"error creating sftp client: %w","messagePattern":"error creating sftp client: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"util/pkg/vfs/sshfs.go","lineNumber":60,"sourceCode":"\tMode os.FileMode\n}\n\nvar _ Path = &SSHPath{}\n\nfunc NewSSHPath(client *ssh.Client, server string, path string, sudo bool) *SSHPath {\n\treturn &SSHPath{\n\t\tclient: client,\n\t\tserver: server,\n\t\tpath:   path,\n\t\tsudo:   sudo,\n\t}\n}\n\nfunc (p *SSHPath) newClient(ctx context.Context) (*sftp.Client, error) {\n\tif !p.sudo {\n\t\tsftpClient, err := sftp.NewClient(p.client)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error creating sftp client: %w\", err)\n\t\t}\n\n\t\treturn sftpClient, nil\n\t}\n\ts, err := p.client.NewSession()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error creating sftp client (in new-session): %w\", err)\n\t}\n\n\tstdin, err := s.StdinPipe()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error creating sftp client (at stdin pipe): %w\", err)\n\t}\n\tstdout, err := s.StdoutPipe()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error creating sftp client (at stdout pipe): %w\", err)\n\t}\n","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/util/pkg/vfs/sshfs.go#L42-L78","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Ensure the remote sshd_config contains `Subsystem sftp /usr/lib/openssh/sftp-server` (or equivalent) and restart sshd","Install/verify the sftp-server binary on the remote host","Re-establish the ssh.Client if the connection may have gone stale, then retry","As a workaround, use NewSSHPath with sudo=true so the client runs `sudo sftp-server` over a session instead of the subsystem","Check server logs (/var/log/auth.log) for subsystem or MaxSessions denials"],"exampleFix":"// before (server sshd_config without sftp subsystem)\n# Subsystem sftp /usr/lib/openssh/sftp-server\n// after\nSubsystem sftp internal-sftp\n# then: sudo systemctl restart sshd","handlingStrategy":"retry","validationCode":"// probe the sftp subsystem before using the VFS path\nsession, err := client.NewSession()\nif err == nil {\n\tdefer session.Close()\n\tout, err := session.CombinedOutput(\"/usr/lib/openssh/sftp-server -v 2>&1 | head -1 || which sftp-server\")\n\t_ = out\n\tif err != nil { log.Printf(\"warning: sftp-server not found on host: %v\", err) }\n}","typeGuard":"func isSFTPSubsystemError(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"error creating sftp client\") &&\n\t\t!strings.Contains(err.Error(), \"new-session\")\n}","tryCatchPattern":"sftpClient, err := path.(*vfs.SSHPath) // operations are on the path itself\nif err := p.Remove(ctx); err != nil {\n\tif strings.Contains(err.Error(), \"error creating sftp client\") {\n\t\t// retry once with a fresh ssh.Client\n\t\tclient, derr := ssh.Dial(\"tcp\", host, cfg)\n\t\tif derr == nil {\n\t\t\tp = vfs.NewSSHPath(client, host, path, sudo)\n\t\t\treturn p.Remove(ctx)\n\t\t}\n\t}\n\treturn err\n}","preventionTips":["Verify the target host's sshd_config declares a Subsystem sftp line","Confirm openssh-sftp-server (or internal-sftp) is available on the host","Recreate ssh.Client connections after idle periods instead of reusing stale ones","Consider sudo=true paths only when the host has /usr/lib/openssh/sftp-server and passwordless sudo","Watch sshd auth logs for subsystem rejections when triaging"],"tags":["ssh","sftp","vfs","network"],"backgroundTag":"sftp-subsystem-unavailable","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}