{"record":{"id":"d541312c8afa80d8","repo":"kubernetes/kops","slug":"parsing-private-key-q-v","errorCode":null,"errorMessage":"parsing private key %q: %v","messagePattern":"parsing private key %q: (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/kops/toolbox_dump.go","lineNumber":169,"sourceCode":"\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tcloudResources = d\n\t}\n\n\tif options.Dir != \"\" {\n\t\tprivateKeyPath := options.PrivateKey\n\t\tif strings.HasPrefix(privateKeyPath, \"~/\") {\n\t\t\tprivateKeyPath = filepath.Join(os.Getenv(\"HOME\"), privateKeyPath[2:])\n\t\t}\n\t\tkey, err := os.ReadFile(privateKeyPath)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"reading private key %q: %v\", privateKeyPath, err)\n\t\t}\n\n\t\tparsedKey, err := ssh.ParseRawPrivateKey(key)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"parsing private key %q: %v\", privateKeyPath, err)\n\t\t}\n\n\t\tsigner, err := ssh.NewSignerFromKey(parsedKey)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"creating signer for private key %q: %v\", privateKeyPath, err)\n\t\t}\n\n\t\tcontextName := cluster.ObjectMeta.Name\n\t\tclientGetter := genericclioptions.NewConfigFlags(true)\n\t\tclientGetter.Context = &contextName\n\n\t\tvar nodes corev1.NodeList\n\n\t\t// TODO: We should use the factory to get the kubeconfig\n\t\tkubeConfig, err := clientGetter.ToRESTConfig()\n\t\tif err != nil {\n\t\t\tklog.Warningf(\"cannot load kubeconfig settings for %q: %v\", contextName, err)\n\t\t} else {","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/cmd/kops/toolbox_dump.go#L151-L187","documentation":"After reading the private key file, toolbox dump parses it with ssh.ParseRawPrivateKey. This error wraps a parse failure: the file content is not a recognized PEM private key, the key is encrypted (passphrase-protected keys are not supported by ParseRawPrivateKey), or the file is corrupt/truncated.","triggerScenarios":"os.ReadFile succeeded but ssh.ParseRawPrivateKey(key) returns an error because the bytes are not a valid unencrypted PEM private key (RSA/ECDSA/Ed25519).","commonSituations":"Pointing at a passphrase-protected key (ParseRawPrivateKey cannot decrypt); passing a public key (.pub) or a certificate; key generated in an unsupported format (PuTTY .ppk, or new OpenSSH format handled differently by the vendored golang.org/x/crypto version); file truncated by a failed scp/copy.","solutions":["Confirm the file is a private key: head -1 should show -----BEGIN ... PRIVATE KEY----- and it must not be the .pub file.","Remove the passphrase or use a keyless copy: ssh-keygen -p -f <key> with an empty new passphrase.","Convert unsupported formats (PuTTY: puttygen key.ppk -O private-openssh -o key.pem).","Regenerate a fresh unencrypted key (ssh-keygen -t ed25519 -N '') if the file is corrupt."],"exampleFix":"// before\nkops toolbox dump --private-key id_rsa.enc  # passphrase-protected -> parse error\n// after\nssh-keygen -p -f id_rsa.enc   # remove passphrase\nkops toolbox dump --private-key id_rsa.enc","handlingStrategy":"validation","validationCode":"head -1 \"$KEY_PATH\" | grep -q '^-----BEGIN.*PRIVATE KEY-----' || { echo \"$KEY_PATH is not a private key (or is the .pub)\"; exit 1; }\nssh-keygen -y -P \"\" -f \"$KEY_PATH\" >/dev/null || { echo \"key is encrypted or unparseable\"; exit 1; }","typeGuard":null,"tryCatchPattern":"parsedKey, err := ssh.ParseRawPrivateKey(key)\nif err != nil {\n    return fmt.Errorf(\"parsing private key %q (encrypted or unsupported format?): %w; consider 'ssh-keygen -p -f %s' to remove passphrase\", privateKeyPath, err, privateKeyPath)\n}","preventionTips":["Keep dump-only keys passphrase-less and 600-permissioned","Never use PuTTY .ppk; convert to OpenSSH PEM format first","Sanity-check keys with ssh-keygen -y -f before automation","Detect the .pub mistake: private keys never end in .pub"],"tags":["kops","ssh","key-parsing"],"backgroundTag":"ssh-private-key-parse-error","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"}