kubernetes/kops · error

error loading private key %q: %v

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.

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)

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.