kubernetes/kops · error
failed to SSH to %q (with user %q): %w
Error message
failed to SSH to %q (with user %q): %w
What it means
With agent-based auth configured, ssh.Dial to host:port failed — TCP unreachable, SSH handshake failure, host unreachable, or the server rejected the agent key (auth attempts exhausted). The HostKeyCallback here accepts any host key, so this is not a host-key failure.
Source
Thrown at pkg/commands/toolbox_enroll.go:329
return nil, fmt.Errorf("SSH agent has no keys")
}
sshConfig := &ssh.ClientConfig{
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
klog.Warningf("accepting SSH key %v for %q", key, hostname)
return nil
},
Auth: []ssh.AuthMethod{
// Use a callback rather than PublicKeys so we only consult the
// agent once the remote server wants it.
ssh.PublicKeysCallback(agentClient.Signers),
},
User: sshUser,
}
// Use net.JoinHostPort so that IPv6 addresses are bracketed correctly.
sshClient, err := ssh.Dial("tcp", net.JoinHostPort(host, strconv.Itoa(sshPort)), sshConfig)
if err != nil {
return nil, fmt.Errorf("failed to SSH to %q (with user %q): %w", host, sshUser, err)
}
return &SSHHost{
hostname: host,
sshClient: sshClient,
sudo: sudo,
}, nil
}
func (s *SSHHost) readFile(ctx context.Context, path string) ([]byte, error) {
p := vfs.NewSSHPath(s.sshClient, s.hostname, path, s.sudo)
return p.ReadFile(ctx)
}
func (s *SSHHost) writeFile(ctx context.Context, path string, data io.ReadSeeker) error {
p := vfs.NewSSHPath(s.sshClient, s.hostname, path, s.sudo)
return p.WriteFile(ctx, data, nil)
}View on GitHub (pinned to 4c8573c808)
Solutions
- Test connectivity: nc -vz <host> <port> and ssh -p <port> <user>@<host>
- Verify security group / firewall allows TCP 22 (or custom port) from your source IP
- Confirm the agent key is in the target user's authorized_keys
- Check the wrapped error: 'connection refused' vs 'handshake failed: ssh: unable to authenticate' points to port vs key problems
Example fix
// before sshHost, err := NewSSHHost(ctx, "10.0.0.5", 2022, "root", true) // port 2022 blocked // after # verify first: ssh -p 22 ubuntu@10.0.0.5 sshHost, err := NewSSHHost(ctx, "10.0.0.5", 22, "ubuntu", true)
Defensive patterns
Strategy: retry
Validate before calling
if err := exec.Command("ssh", "-p", strconv.Itoa(port),
"-o", "BatchMode=yes", "-o", "StrictHostKeyChecking=no",
user+"@"+host, "true").Run(); err != nil {
return fmt.Errorf("prerequisite ssh to %s@%s:%d failed: %w", user, host, port, err)
} Type guard
func sshReachable(host string, port int) bool {
conn, err := net.DialTimeout("tcp", net.JoinHostPort(host, strconv.Itoa(port)), 5*time.Second)
if err != nil { return false }
conn.Close()
return true
} Try / catch
var sshHost *SSHHost
err := retry.Do(func() error {
sshHost, err = NewSSHHost(ctx, hostAddr, port, user, sudo)
return err
}, retry.Attempts(3), retry.Delay(5*time.Second))
if err != nil {
return fmt.Errorf("ssh to %q unreachable after retries; check firewall/key auth: %w", hostAddr, err)
} Prevention
- Test plain ssh <user>@<host> -p <port> before enroll
- Open TCP 22 (or custom port) in the cloud security group for your IP
- Ensure the agent key is present in the target user's authorized_keys
- Use the correct default SSH user for the cloud image (e.g. ubuntu/admin/ec2-user)
When it happens
Trigger: Wrong host/IP or port (default 22 not open), security group/firewall blocking SSH, host powered off or not yet provisioned, the SSH user lacks authorized_keys on the target, or the agent key isn't authorized on the host.
Common situations: Enrolling a freshly created VM before its network/security-group rules allow SSH; using the internal vs external IP incorrectly; enrolling with a user other than the one holding the authorized key (e.g. root vs admin on cloud images).
Related errors
- unable to SSH to %q: %v
- fetching %q: %v
- SSH agent has no keys
- failed to start SSH session: %w
- connecting: %w
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/78630645023bbfdf.
Report an issue: GitHub.