kubernetes/kops · error
keypair has no private key
Error message
keypair has no private key
What it means
The specified keypair item exists but has no private key stored (item.PrivateKey == nil). Only keypairs holding both a private key and a certificate can become the primary signing keypair; certificates-only items (e.g. legacy entries or keysets where private keys are not retained) cannot be promoted.
Source
Thrown at cmd/kops/promote_keypair.go:185
if item.PrivateKey != nil && item.DistrustTimestamp == nil && item.Certificate != nil {
itemId, ok := big.NewInt(0).SetString(id, 10)
if ok && highestCandidateId.Cmp(itemId) < 0 {
highestCandidateId = itemId
}
}
}
keypairID = highestCandidateId.String()
if keypairID == keyset.Primary.Id {
fmt.Fprintf(out, "No %s keypair newer than current primary %s\n", name, keypairID)
return nil
}
} else if item := keyset.Items[keypairID]; item != nil {
if item.DistrustTimestamp != nil {
return fmt.Errorf("keypair is distrusted")
}
if item.PrivateKey == nil {
return fmt.Errorf("keypair has no private key")
}
if item.Certificate == nil {
return fmt.Errorf("keypair has no certificate")
}
} else {
return fmt.Errorf("keypair not found")
}
keyset.Primary = keyset.Items[keypairID]
err = keyStore.StoreKeyset(ctx, name, keyset)
if err != nil {
return fmt.Errorf("writing keyset: %v", err)
}
fmt.Fprintf(out, "Promoted %s %s\n", name, keypairID)
return nil
}
View on GitHub (pinned to 4c8573c808)
Solutions
- Pick a keypair ID that includes a private key — `kops get keypairs <keyset>` shows which entries are usable for promotion.
- Omit the ID entirely (`kops promote keypair <keyset>`) so kOps auto-selects the newest candidate that has a private key and is not distrusted.
- If no keypair with a private key exists, issue a new one (`kops create keypair <keyset>`) and then promote it.
- Restore the private key from a state-store backup if it was deleted inadvertently.
Example fix
// before: ID refers to a certificate-only item kops promote keypair kubernetes-ca 1234567890 --name c.example.com // error: keypair has no private key // after: let kOps choose the newest keypair with a private key kops promote keypair kubernetes-ca --name c.example.com
Defensive patterns
Strategy: validation
Validate before calling
// shell: confirm the item has a usable private key before promoting
// (auto-promote mode already filters on PrivateKey != nil; when passing an ID, verify first)
kops get keypairs "$KEYSET" --name "$CLUSTER" --state "$KOPS_STATE_STORE" -o json \
| jq -e --arg id "$KEYPAIR_ID" '.items[] | select(.id == $id) | .privateKey != null' >/dev/null \
|| { echo "$KEYPAIR_ID has no private key; omit the ID to auto-select a promotable keypair"; exit 1; } Try / catch
if kops promote keypair "$KEYSET" "$KEYPAIR_ID" --name "$CLUSTER" 2>&1 | grep -q 'has no private key'; then echo "$KEYPAIR_ID is certificate-only; promoting newest keypair with a private key instead" kops promote keypair "$KEYSET" --name "$CLUSTER" else kops promote keypair "$KEYSET" "$KEYPAIR_ID" --name "$CLUSTER" fi
Prevention
- Prefer omitting the keypair ID so kOps only considers items with a private key.
- Verify an entry holds both a certificate and a private key via `kops get keypairs` before promoting a specific ID.
- Avoid deleting or pruning private keys from the keystore while old entries may still be needed.
- Issue a fresh keypair (`kops create keypair`) when only certificate-only entries remain.
When it happens
Trigger: `kops promote keypair <keyset> <id>` where the item for <id> exists in keyset.Items but its PrivateKey is nil — the keypair was issued/stored as certificate-only, or the private-key portion was removed/distrusted from the store.
Common situations: Promoting an old CA keypair whose private key was pruned during cleanup; keyset entries created only with certificates (e.g. imported certs without keys); automation referencing an ID from `kops get keypairs` output that lists cert-only entries.
Related errors
- adding keypair to %q is not supported
- error getting keystore: %v
- error loading private key %q: %v
- the first keypair added to a keyset must be primary
- promoting keypairs for %q is not supported
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/2d6b043b1ab5eb7a.
Report an issue: GitHub.