{"record":{"id":"6a4428667d92764e","repo":"kubernetes/kops","slug":"error-reading-public-key-q-after-creation-w","errorCode":null,"errorMessage":"error reading public key %q (after creation): %w","messagePattern":"error reading public key %q \\(after creation\\): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/commands/toolbox_enroll.go","lineNumber":192,"sourceCode":"\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\n\thostname, err := sshTarget.getHostname(ctx)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\thost := &v1alpha2.Host{}\n\thost.SetGroupVersionKind(v1alpha2.SchemeGroupVersion.WithKind(\"Host\"))\n\thost.Namespace = \"kops-system\"\n\thost.Name = hostname\n\thost.Spec.InstanceGroup = options.InstanceGroup\n\thost.Spec.PublicKey = string(publicKeyBytes)\n\thost.Spec.PodCIDRs = options.PodCIDRs\n","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/commands/toolbox_enroll.go#L174-L210","documentation":"When the public key does not exist, kops runs a script on the target to generate a keypair, then re-reads the public key. If that second read fails (the creation script ran but the file still isn't readable/present), this distinct error tells you generation itself didn't produce a usable key.","triggerScenarios":"ssh-keygen missing or failing on the target (so no .pub file appears), the creation script writing to a different path than publicKeyPath, or read failures right after creation (permissions, SFTP errors).","commonSituations":"Minimal OS images without openssh-keygen/ssh-keygen installed; read-only /root/.ssh; SELinux or immutable /etc/ssh preventing key generation.","solutions":["SSH into the host and run the keygen manually (`ssh-keygen -t ed25519 -N '' -f ~/.ssh/id_ed25519`) to see the real failure","Install/repair ssh-keygen on the target (e.g. `apt-get install openssh-client`)","Ensure /root/.ssh exists, is writable, and the keygen output path matches what kops expects"],"exampleFix":"// on the target host\n// before: bash: ssh-keygen: command not found\n// after\napt-get update && apt-get install -y openssh-client","handlingStrategy":"validation","validationCode":"ssh -p \"$PORT\" root@$HOST 'command -v ssh-keygen >/dev/null && [ -w ~/.ssh ]' \\\n  || { echo \"target cannot generate keys: install openssh-client and ensure ~/.ssh is writable\"; exit 1; }","typeGuard":null,"tryCatchPattern":"if err := RunToolboxEnroll(...); err != nil && strings.Contains(err.Error(), \"after creation\") {\n    log.Printf(\"key auto-generation failed on target; create the key manually: %v\", err)\n    return err\n}","preventionTips":["Bake ssh-keygen/openssh-client into bare-metal images","Pre-provision the keypair so kops skips generation","Ensure ~/.ssh exists and is writable by the enroll user"],"tags":["ssh","bare-metal","key-generation"],"backgroundTag":"ssh-key-generation-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"}