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

  1. 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.
  2. Confirm the value is a PEM private key block ('RSA PRIVATE KEY', 'EC PRIVATE KEY', or 'PRIVATE KEY') — not a certificate or public key.
  3. If the value is base64, ensure it is standard (StdEncoding) base64 of the full PEM text and decodes cleanly.
  4. 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

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


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/094f49bd859080e8. Report an issue: GitHub.