{"record":{"id":"094f49bd859080e8","repo":"kubernetes/kops","slug":"error-parsing-private-key-v","errorCode":null,"errorMessage":"error parsing private key: %v","messagePattern":"error parsing private key: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/pki/privatekey.go","lineNumber":125,"sourceCode":"func (k *PrivateKey) UnmarshalJSON(b []byte) (err error) {\n\ts := \"\"\n\tif err := json.Unmarshal(b, &s); err == nil {\n\t\tr, err := parsePEMPrivateKey([]byte(s))\n\t\tif err != nil {\n\t\t\t// Alternative form: Check if base64 encoded\n\t\t\t// TODO: Do we need this?  I think we need this only on nodeup, but maybe we could just not base64-it?\n\t\t\td, err2 := base64.StdEncoding.DecodeString(s)\n\t\t\tif err2 == nil {\n\t\t\t\tr2, err2 := parsePEMPrivateKey(d)\n\t\t\t\tif err2 == nil {\n\t\t\t\t\tklog.Warningf(\"used base64 decode of PrivateKey\")\n\t\t\t\t\tr = r2\n\t\t\t\t\terr = nil\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"error parsing private key: %v\", err)\n\t\t\t}\n\t\t}\n\t\tk.Key = r\n\t\treturn nil\n\t}\n\n\treturn fmt.Errorf(\"unknown format for private key: %q\", string(b))\n}\n\nfunc (k *PrivateKey) MarshalJSON() ([]byte, error) {\n\tvar data bytes.Buffer\n\t_, err := k.WriteTo(&data)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error writing SSL private key: %v\", err)\n\t}\n\treturn json.Marshal(data.String())\n}\n","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/pki/privatekey.go#L107-L143","documentation":"PrivateKey.UnmarshalJSON first tries to decode the JSON string as a PEM private key, then as base64-encoded PEM; if both parsePEMPrivateKey attempts fail, it returns 'error parsing private key' wrapping the underlying reason (bad PEM, wrong DER, unsupported algorithm).","triggerScenarios":"Unmarshaling JSON into a struct with a *PrivateKey field where the string value is not valid PEM (or not valid base64-then-PEM), e.g. a certificate instead of a key, a public key, or truncated key data.","commonSituations":"Hand-editing kops cluster spec / state store entries and pasting a cert where a key belongs; base64 wrapping conventions differing between nodeup and the API; keys with a leading BOM, Windows line endings, or missing header lines.","solutions":["Check the wrapped error text: 'unable to decode PEM' means the data is not PEM at all; DER parse errors mean the PEM body is corrupt.","Confirm the value is a PEM private key block ('RSA PRIVATE KEY', 'EC PRIVATE KEY', or 'PRIVATE KEY') — not a certificate or public key.","If the value is base64, ensure it is standard (StdEncoding) base64 of the full PEM text and decodes cleanly.","Regenerate the key with kops replace/create (e.g. 'kops create keypair') rather than hand-crafting state store contents."],"exampleFix":"// before\n{\"key\": \"-----BEGIN CERTIFICATE-----...\"} // cert, not key\n// after\n{\"key\": \"-----BEGIN RSA PRIVATE KEY-----\\nMIIEpA...\\n-----END RSA PRIVATE KEY-----\"}","handlingStrategy":"validation","validationCode":"if !strings.HasPrefix(s, \"-----BEGIN\") {\n    if d, err := base64.StdEncoding.DecodeString(s); err == nil {\n        s = string(d)\n    }\n}\nif !strings.Contains(s, \"PRIVATE KEY\") {\n    return fmt.Errorf(\"value is not a PEM private key\")\n}","typeGuard":null,"tryCatchPattern":"if err := json.Unmarshal(data, &spec); err != nil {\n    if strings.Contains(err.Error(), \"error parsing private key\") {\n        // inspect key field: wrong material or corrupt PEM\n    }\n    return err\n}","preventionTips":["Never paste certificates where private keys belong in cluster specs.","Keep PEM newlines intact (escaped as \\n in JSON) — avoid editor tools that mangle them.","Validate keyset entries in the state store before upgrading kops versions."],"tags":["pki","json","pem-parsing"],"backgroundTag":"pem-parse-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"}