kubernetes/kops · error

error loading private key %s/%s: %v

Error message

error loading private key %s/%s: %v

What it means

parseKeyset decodes key.PrivateMaterial with pki.ParsePEMPrivateKey; invalid private-key bytes abort the keyset load with 'error loading private key <name>/<id>: <underlying>'. Like the certificate counterpart, one bad item prevents the entire keyset from being returned. Located at upup/pkg/fi/clientset_castore.go:97.

Source

Thrown at upup/pkg/fi/clientset_castore.go:97

			Id: key.Id,
		}
		if key.DistrustTimestamp != nil {
			distrustTimestamp := key.DistrustTimestamp.Time
			ki.DistrustTimestamp = &distrustTimestamp
		}
		if len(key.PublicMaterial) != 0 {
			cert, err := pki.ParsePEMCertificate(key.PublicMaterial)
			if err != nil {
				klog.Warningf("key public material was %s", key.PublicMaterial)
				return nil, fmt.Errorf("error loading certificate %s/%s: %v", name, key.Id, err)
			}
			ki.Certificate = cert
		}

		if len(key.PrivateMaterial) != 0 {
			privateKey, err := pki.ParsePEMPrivateKey(key.PrivateMaterial)
			if err != nil {
				return nil, fmt.Errorf("error loading private key %s/%s: %v", name, key.Id, err)
			}
			ki.PrivateKey = privateKey
		}

		keyset.Items[key.Id] = ki
	}

	keyset.Primary = keyset.Items[FindPrimary(o).Id]

	return keyset, nil
}

// loadKeyset gets the named Keyset and the format of the Keyset.
func (c *ClientsetCAStore) loadKeyset(ctx context.Context, name string) (*Keyset, error) {
	o, err := c.clientset.Keysets(c.namespace).Get(ctx, name, metav1.GetOptions{})
	if err != nil {
		if errors.IsNotFound(err) {
			return nil, nil

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Check the stored PrivateMaterial and re-encode it as an unencrypted PEM private key (openssl pkey -in key.pem -out key-unenc.pem)
  2. Re-issue/rotate the keypair so valid private material is stored in the Keyset
  3. Restore the Keyset object from backup or remove the corrupt item

Example fix

// before: encrypted PEM kops cannot parse
// -----BEGIN ENCRYPTED PRIVATE KEY-----
// after: decrypt before storing
openssl pkey -in key.pem -passin pass:secret -out key-unenc.pem
Defensive patterns

Strategy: try-catch

Validate before calling

if !pemHasBlock(item.PrivateMaterial, "PRIVATE KEY", "RSA PRIVATE KEY", "EC PRIVATE KEY") {
	return fmt.Errorf("keyset item private material is not an unencrypted PEM private key")
}
if _, err := pki.ParsePEMPrivateKey(item.PrivateMaterial); err != nil {
	return fmt.Errorf("private key will fail to load: %w", err)
}

Type guard

func isPEMPrivateKey(b []byte) bool {
	block, _ := pem.Decode(b)
	return block != nil && strings.HasSuffix(block.Type, "PRIVATE KEY")
}

Try / catch

keyset, err := store.FindKeyset(ctx, name)
if err != nil {
	if strings.Contains(err.Error(), "error loading private key") {
		// rotate/re-issue the keypair for this keyset
	}
	return err
}

Prevention

When it happens

Trigger: A Keyset item whose PrivateMaterial is corrupt, truncated, encrypted (passphrase-protected PEM kops cannot parse), or not a PRIVATE KEY/EC PRIVATE KEY/RSA PRIVATE KEY block.

Common situations: Keys stored with passphrase encryption from an external tool; corrupted etcd/registry entries; keys re-encoded by another tool into an unsupported format.

Related errors


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