kubernetes/kops · error
error creating sftp client (at stdin pipe): %w
Error message
error creating sftp client (at stdin pipe): %w
What it means
SSHPath.newClient in util/pkg/vfs/sshfs.go wraps errors from s.StdinPipe() with this message on the sudo=true path. After opening an SSH session, pipes for stdin/stdout are created to talk to the remote sftp-server process; a failure here means the session could not provide the stdin pipe, indicating the session channel is in a bad or already-closed state.
Source
Thrown at util/pkg/vfs/sshfs.go:72
}
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)
}
err = s.Start("sudo /usr/lib/openssh/sftp-server")
if err != nil {
return nil, fmt.Errorf("error creating sftp client (executing 'sudo /usr/lib/openssh/sftp-server'): %w", err)
}
c, err := sftp.NewClientPipe(stdout, stdin)
if err != nil {
return nil, fmt.Errorf("error starting sftp (executing 'sudo /usr/lib/openssh/sftp-server'): %w", err)
}
return c, nil
}
View on GitHub (pinned to 4c8573c808)
Solutions
- Re-establish the ssh.Client and retry the operation — the connection was likely closed mid-setup
- Avoid sharing one ssh.Client across concurrent goroutines without synchronization
- Enable SSH keepalives to keep the connection alive between VFS operations
- Check sshd server logs for why the channel was torn down (e.g. session limits)
Example fix
// before
client, err := ssh.Dial("tcp", host, cfg) // reused long after dial
// after
// keep connection alive and re-dial on failure:
client, err := ssh.Dial("tcp", host, cfg)
if err != nil {
return nil, fmt.Errorf("re-establishing ssh connection: %w", err)
}
// set ClientConfig.HostKeyCallback/Timeout and a KeepAlive via client.SendRequest loop Defensive patterns
Strategy: retry
Validate before calling
// verify the connection is alive right before VFS operations
_, err := client.SendRequest("keepalive@openssh.com", true, nil)
if err != nil {
client, err = ssh.Dial("tcp", host, cfg) // re-dial stale connection
if err != nil { log.Fatalf("ssh connection dead: %v", err) }
} Type guard
func isStdinPipeError(err error) bool {
return err != nil && strings.Contains(err.Error(), "sftp client (at stdin pipe)")
} Try / catch
err := p.ReadDir(ctx)
if err != nil && strings.Contains(err.Error(), "error creating sftp client (at stdin pipe)") {
// connection died mid-setup: rebuild and retry once
client, derr := ssh.Dial("tcp", host, cfg)
if derr == nil {
p = vfs.NewSSHPath(client, host, path, true)
return p.ReadDir(ctx)
}
}
return err Prevention
- Send SSH keepalive requests periodically to keep the connection healthy
- Re-dial the ssh.Client at the first sign of channel/pipe errors
- Avoid concurrent use of a single ssh.Client from multiple goroutines
- Minimize time between dialing and performing VFS operations
- Check sshd logs for abrupt channel teardowns on the target host
When it happens
Trigger: SSHPath operations with sudo=true where s.StdinPipe() returns an error after NewSession() succeeded — typically when the underlying ssh connection was closed between opening the session and requesting the pipe, or the session was rejected/reaped immediately by the server.
Common situations: Race with connection teardown (server closed the connection right after session setup); broken ssh.Client sharing across goroutines leading to closed channels; server abruptly closing the channel due to policy limits.
Related errors
- error creating sftp client: %w
- error creating sftp client (in new-session): %w
- writing to sftp temp file: %w
- error opening file %s over sftp: %w
- error loading channel %q: %v
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/dfab81dce61995c6.
Report an issue: GitHub.