{"record":{"id":"a69c41a13bb0af8f","repo":"kubernetes/kops","slug":"error-reading-public-key-q-w","errorCode":null,"errorMessage":"error reading public key %q: %w","messagePattern":"error reading public key %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/commands/toolbox_enroll.go","lineNumber":179,"sourceCode":"\t}\n\n\tif err := enrollHost(ctx, fullInstanceGroup, bootstrapData, restConfig, hostData, sshTarget); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\n// buildHostData builds an instance of the Host CRD, based on information in the options and by SSHing to the target host.\nfunc buildHostData(ctx context.Context, sshTarget *SSHHost, options *ToolboxEnrollOptions) (*v1alpha2.Host, error) {\n\tpublicKeyPath := \"/etc/kubernetes/kops/pki/machine/public.pem\"\n\n\tpublicKeyBytes, err := sshTarget.readFile(ctx, publicKeyPath)\n\tif err != nil {\n\t\tif errors.Is(err, fs.ErrNotExist) {\n\t\t\tpublicKeyBytes = nil\n\t\t} else {\n\t\t\treturn nil, fmt.Errorf(\"error reading public key %q: %w\", publicKeyPath, err)\n\t\t}\n\t}\n\n\t// Create the key if it doesn't exist\n\tpublicKeyBytes = bytes.TrimSpace(publicKeyBytes)\n\tif len(publicKeyBytes) == 0 {\n\t\tif _, err := sshTarget.runScript(ctx, scriptCreateKey, ExecOptions{Echo: true}); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tb, err := sshTarget.readFile(ctx, publicKeyPath)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error reading public key %q (after creation): %w\", publicKeyPath, err)\n\t\t}\n\t\tpublicKeyBytes = b\n\t}\n\tklog.Infof(\"public key is %s\", string(publicKeyBytes))\n","sourceCodeStart":161,"sourceCodeEnd":197,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/commands/toolbox_enroll.go#L161-L197","documentation":"buildHostData reads the target's SSH public key (default /root/.ssh/id_ed25519.pub style path) over SSH. If the read fails with any error other than fs.ErrNotExist — e.g. permission denied, connection reset mid-transfer — the command wraps it as \"error reading public key %q\".","triggerScenarios":"The remote key file exists but is unreadable by the SSH user; SFTP/SSH channel errors; the path is a directory; transient network failure during readFile.","commonSituations":"Enrolling hosts where the SSH user isn't root (default is root, but custom configs differ) and cannot read /root/.ssh; hardened images with restrictive permissions on .ssh; flaky networks.","solutions":["Check the wrapped error: fix permissions on the remote key file (`chmod 600 ~/.ssh/id_ed25519; chmod 700 ~/.ssh`) or make it readable by the SSH user","Pre-create a readable public key on the host, or let kops create it by ensuring the key simply does not exist (then it generates one)","Verify SSH connectivity and user: `ssh -p <port> <user>@<host> 'cat <path>'`"],"exampleFix":"// on the target host, before enrolling\n// before: -rw------- root root /root/.ssh/id_ed25519.pub read via non-root user\n// after\nchmod 755 /root/.ssh && chmod 644 /root/.ssh/id_ed25519.pub","handlingStrategy":"try-catch","validationCode":"ssh -p \"$PORT\" \"$USER@$HOST\" 'test -r ~/.ssh/id_ed25519.pub || test ! -e ~/.ssh/id_ed25519.pub' \\\n  || { echo \"public key exists but is not readable by SSH user\"; exit 1; }","typeGuard":null,"tryCatchPattern":"err := RunToolboxEnroll(ctx, f, out, opts)\nif err != nil && strings.Contains(err.Error(), \"error reading public key\") {\n    log.Printf(\"fix remote key permissions or SSH user; cause: %v\", err)\n    return err\n}","preventionTips":["Enroll as root or ensure the SSH user can read the key path","Standardize permissions: 700 ~/.ssh, 644 *.pub on targets","Test `ssh <host> cat <keypath>` before running enroll"],"tags":["ssh","bare-metal","file-read"],"backgroundTag":"ssh-file-read-failed","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}