kubernetes/kops · error
error parsing private key: %v
Error message
error parsing private key: %v
What it means
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).
Source
Thrown at pkg/pki/privatekey.go:125
func (k *PrivateKey) UnmarshalJSON(b []byte) (err error) {
s := ""
if err := json.Unmarshal(b, &s); err == nil {
r, err := parsePEMPrivateKey([]byte(s))
if err != nil {
// Alternative form: Check if base64 encoded
// TODO: Do we need this? I think we need this only on nodeup, but maybe we could just not base64-it?
d, err2 := base64.StdEncoding.DecodeString(s)
if err2 == nil {
r2, err2 := parsePEMPrivateKey(d)
if err2 == nil {
klog.Warningf("used base64 decode of PrivateKey")
r = r2
err = nil
}
}
if err != nil {
return fmt.Errorf("error parsing private key: %v", err)
}
}
k.Key = r
return nil
}
return fmt.Errorf("unknown format for private key: %q", string(b))
}
func (k *PrivateKey) MarshalJSON() ([]byte, error) {
var data bytes.Buffer
_, err := k.WriteTo(&data)
if err != nil {
return nil, fmt.Errorf("error writing SSL private key: %v", err)
}
return json.Marshal(data.String())
}
View on GitHub (pinned to 4c8573c808)
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.
Example fix
// before
{"key": "-----BEGIN CERTIFICATE-----..."} // cert, not key
// after
{"key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpA...\n-----END RSA PRIVATE KEY-----"} Defensive patterns
Strategy: validation
Validate before calling
if !strings.HasPrefix(s, "-----BEGIN") {
if d, err := base64.StdEncoding.DecodeString(s); err == nil {
s = string(d)
}
}
if !strings.Contains(s, "PRIVATE KEY") {
return fmt.Errorf("value is not a PEM private key")
} Try / catch
if err := json.Unmarshal(data, &spec); err != nil {
if strings.Contains(err.Error(), "error parsing private key") {
// inspect key field: wrong material or corrupt PEM
}
return err
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- unmarshalling authorization token data: %w
- unknown format for private key: %q
- could not parse private key (unable to decode PEM)
- error parsing version spec %q
- error encoding version spec: %v
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/094f49bd859080e8.
Report an issue: GitHub.