kubernetes/kops · error

error loading private key

Error message

error loading private key %q: %v

What it means

After a successful read of the user-supplied --key file, the bytes are parsed with pki.ParsePEMPrivateKey. Content that isn't a valid PEM private key (or an unsupported key algorithm) produces this error, which embeds the raw key bytes in the message.

Solutions

  1. Verify the file is an unencrypted PEM private key: `head -1 file` should show -----BEGIN ... PRIVATE KEY-----.
  2. Decrypt first if needed: `openssl pkey -in encrypted.key -out decrypted.key`.
  3. Ensure you pass the private key, not the certificate (--cert is the separate flag).
  4. Convert non-PEM formats: `openssl rsa -inform DER -in key.der -out key.pem` (or export from PuTTYgen to OpenSSH PEM).
  5. Check the algorithm is supported (e.g. RSA/ECDSA) for the target keyset.

Example fix

// before
kops create keypair cluster.k8s.local --keyset ca --key ca.crt   # certificate, not a key
// after
kops create keypair cluster.k8s.local --keyset ca --cert ca.crt --key ca.key
Defensive patterns

Strategy: validation

Validate before calling

grep -q '^-----BEGIN .*PRIVATE KEY-----$' "$KEY_PATH" || { echo "$KEY_PATH is not a PEM private key"; exit 1; }
openssl pkey -in "$KEY_PATH" -noout >/dev/null 2>&1 || { echo "key unreadable/encrypted/unsupported"; exit 1; }

Try / catch

if ! out=$(kops create keypair "$CLUSTER" --keyset ca --key "$KEY" 2>&1); then
  case "$out" in
    *"error loading private key"*) echo "Re-encode the key: openssl pkey -in "$KEY" -out key.pem";;
  esac
fi

Prevention

When it happens

Trigger: `--key <path>` where the file's contents fail pki.ParsePEMPrivateKey — non-PEM data, a public key instead of private, a certificate, encrypted PEM, or unsupported algorithm (cmd/kops/create_keypair.go:198).

Common situations: Passing the .crt/.pub file by mistake; passing an encrypted key with a passphrase (kOps won't prompt); keys in non-PEM formats (e.g. raw DER or PuTTY PPK); wrong key type for the keyset.

Related errors


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

Appendix: source

Thrown at cmd/kops/create_keypair.go:198

		}
	}

	return nil
}

func createKeypair(ctx context.Context, out io.Writer, options *CreateKeypairOptions, name string, keyStore fi.CAStore) error {
	var err error
	var privateKey *pki.PrivateKey
	if options.PrivateKeyPath != "" {
		options.PrivateKeyPath = utils.ExpandPath(options.PrivateKeyPath)
		privateKeyBytes, err := os.ReadFile(options.PrivateKeyPath)
		if err != nil {
			return fmt.Errorf("error reading user provided private key %q: %v", options.PrivateKeyPath, err)
		}

		privateKey, err = pki.ParsePEMPrivateKey(privateKeyBytes)
		if err != nil {
			return fmt.Errorf("error loading private key %q: %v", privateKeyBytes, err)
		}
	}

	var cert *pki.Certificate
	if options.CertPath == "" {
		if privateKey == nil {
			privateKey, err = pki.GeneratePrivateKey()
			if err != nil {
				return fmt.Errorf("error generating private key: %v", err)
			}
		}

		serial := pki.BuildPKISerial(time.Now().UnixNano())
		req := pki.IssueCertRequest{
			Type:       "ca",
			Subject:    pkix.Name{CommonName: name, SerialNumber: serial.String()},
			Serial:     serial,
			PrivateKey: privateKey,

View on GitHub (pinned to 4c8573c808)