kubernetes/kops · error
private key not provided for primary item
Error message
private key not provided for primary item
What it means
AddItem validates that a primary keyset item always carries a certificate AND a private key. When privateKey is nil but primary=true, kOps would end up with a primary keypair it cannot use for signing, so construction aborts with 'private key not provided for primary item'. It is an argument-validation guard inside upup/pkg/fi/ca.go:204.
Source
Thrown at upup/pkg/fi/ca.go:204
func NewKeyset(cert *pki.Certificate, privateKey *pki.PrivateKey) (*Keyset, error) {
keyset := &Keyset{
Items: map[string]*KeysetItem{},
}
_, err := keyset.AddItem(cert, privateKey, true)
if err != nil {
return nil, err
}
return keyset, nil
}
// AddItem adds an item to the keyset
func (k *Keyset) AddItem(cert *pki.Certificate, privateKey *pki.PrivateKey, primary bool) (item *KeysetItem, err error) {
if cert == nil {
return item, fmt.Errorf("no certificate provided")
}
if privateKey == nil && primary {
return item, fmt.Errorf("private key not provided for primary item")
}
if !primary && k.Primary == nil {
return item, fmt.Errorf("cannot add secondary item when no existing primary item")
}
highestId := big.NewInt(0)
for id := range k.Items {
itemId, ok := big.NewInt(0).SetString(id, 10)
if ok && highestId.Cmp(itemId) < 0 {
highestId = itemId
}
}
// Make sure any subsequently created items will have ids that compare higher.
// If setting a primary, make sure its id doesn't compare lower than existing items.
idNumber := pki.BuildPKISerial(time.Now().UnixNano())
if cert.Certificate.SerialNumber.Cmp(idNumber) <= 0 &&View on GitHub (pinned to 4c8573c808)
Solutions
- Provide the matching pki.PrivateKey along with the certificate when primary=true
- If only a certificate is intended, call AddItem with primary=false after a primary item exists
- Verify the source PEM/key material actually contains a PRIVATE KEY block, not just a CERTIFICATE block
- Fix upstream loaders so private material is parsed before AddItem is invoked
Example fix
// before
keyset.AddItem(cert, nil, true)
// after
privateKey, err := pki.ParsePEMPrivateKey(privateKeyPEM)
if err != nil { return err }
keyset.AddItem(cert, privateKey, true) Defensive patterns
Strategy: validation
Validate before calling
if cert == nil || privateKey == nil {
return fmt.Errorf("primary item requires both certificate and private key")
}
item, err := keyset.AddItem(cert, privateKey, true) Prevention
- Always pair the certificate with its parsed private key before calling AddItem
- Use primary=false for cert-only additions once a primary exists
- Unit-test keyset construction with real PEM fixtures
When it happens
Trigger: Calling Keyset.AddItem(cert, nil, true), or building a keyset via NewKeyset/parsing paths where a cert was parsed successfully but the PEM private key was absent or failed to parse.
Common situations: Rotating a CA/keypair from a bundle that contains only the certificate (public .crt/.pem) without the matching private key; a secrets store entry with public material but empty private material; passing a placeholder nil key in test code.
Related errors
- cannot add secondary item when no existing primary item
- parsing keyset %q: %w
- unhandled secret type %q: %v
- adding keypair to %q is not supported
- promoting keypairs for %q is not supported
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/06d2311a09d09667.
Report an issue: GitHub.