{"record":{"id":"260a6a7da9e8fa4a","repo":"kubernetes/kops","slug":"failed-to-get-signers-w","errorCode":null,"errorMessage":"failed to get signers: %w","messagePattern":"failed to get signers: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/commands/toolbox_enroll.go","lineNumber":307,"sourceCode":"}\n\n// NewSSHHost creates a new SSHHost.\nfunc NewSSHHost(ctx context.Context, host string, sshPort int, sshUser string, sudo bool) (*SSHHost, error) {\n\tsocket := os.Getenv(\"SSH_AUTH_SOCK\")\n\tif socket == \"\" {\n\t\treturn nil, fmt.Errorf(\"cannot connect to SSH agent; SSH_AUTH_SOCK env variable not set\")\n\t}\n\tconn, err := net.Dial(\"unix\", socket)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to connect to SSH agent with SSH_AUTH_SOCK %q: %w\", socket, err)\n\t}\n\n\tagentClient := agent.NewClient(conn)\n\n\tsigners, err := agentClient.Signers()\n\tif err != nil {\n\t\t_ = conn.Close()\n\t\treturn nil, fmt.Errorf(\"failed to get signers: %w\", err)\n\t}\n\n\tif len(signers) == 0 {\n\t\treturn nil, fmt.Errorf(\"SSH agent has no keys\")\n\t}\n\n\tsshConfig := &ssh.ClientConfig{\n\t\tHostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {\n\t\t\tklog.Warningf(\"accepting SSH key %v for %q\", key, hostname)\n\t\t\treturn nil\n\t\t},\n\t\tAuth: []ssh.AuthMethod{\n\t\t\t// Use a callback rather than PublicKeys so we only consult the\n\t\t\t// agent once the remote server wants it.\n\t\t\tssh.PublicKeysCallback(agentClient.Signers),\n\t\t},\n\t\tUser: sshUser,\n\t}","sourceCodeStart":289,"sourceCodeEnd":325,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/commands/toolbox_enroll.go#L289-L325","documentation":"After dialing the agent socket, the code calls agentClient.Signers() to list keys the agent can sign with. A transport-level failure on the agent protocol (connection closed, protocol error) produces this wrapped error, and the connection is closed.","triggerScenarios":"The unix socket connected but did not behave like an SSH agent — e.g. the path points to a different service's socket, the agent died between dial and Signers(), or the golang.org/x/crypto/ssh/agent handshake failed.","commonSituations":"SSH_AUTH_SOCK pointing at gpg-agent or a custom socket not speaking the SSH agent protocol; agent crashed mid-run; container socket forwarding breaking the stream.","solutions":["Verify the agent works: ssh-add -l must list keys without error","Restart the agent: eval $(ssh-agent -s) && ssh-add","Check SSH_AUTH_SOCK points to a real ssh-agent socket, not gpg-agent's non-SSH socket (enable SSH support in gpg-agent or use the ssh-agent socket path)","Retry the command; if intermittent, inspect agent stability/logs"],"exampleFix":"// before\n$ echo $SSH_AUTH_SOCK\n/run/user/1000/gnupg/S.gpg-agent.extra   # not an SSH agent socket\n// after\n$ export SSH_AUTH_SOCK=$HOME/.gnupg/S.gpg-agent.ssh  # gpg-agent with enable-ssh-support\n# or: eval $(ssh-agent -s) && ssh-add","handlingStrategy":"validation","validationCode":"c, err := net.Dial(\"unix\", os.Getenv(\"SSH_AUTH_SOCK\"))\nif err != nil { return err }\ndefer c.Close()\nsigners, err := agent.NewClient(c).Signers()\nif err != nil { return fmt.Errorf(\"endpoint does not speak SSH agent protocol: %w\", err) }","typeGuard":"func agentProtocolOK() bool {\n    c, err := net.Dial(\"unix\", os.Getenv(\"SSH_AUTH_SOCK\"))\n    if err != nil { return false }\n    defer c.Close()\n    _, err = agent.NewClient(c).Signers()\n    return err == nil\n}","tryCatchPattern":"host, err := NewSSHHost(ctx, hostAddr, port, user, sudo)\nif err != nil && strings.Contains(err.Error(), \"failed to get signers\") {\n    return fmt.Errorf(\"SSH_AUTH_SOCK points to a non-agent socket; check ssh-add -l\")\n}","preventionTips":["Sanity check with ssh-add -l before enrolling","Point SSH_AUTH_SOCK at a real ssh-agent socket, not gpg-agent.extra","Restart a wedged agent with eval $(ssh-agent -s)"],"tags":["ssh","ssh-agent","protocol"],"backgroundTag":"ssh-agent-signers-failed","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"}