kubernetes/kops · error
key %q did not have primary id set
Error message
key %q did not have primary id set
What it means
When includeKeypairID is true, loadCertificates also records the primary keypair's ID in config.KeypairIDs so nodeup can pin/verify the keyset version. This error is thrown when the keyset exists and its certificates serialize fine, but it has no primary item, or the primary item has an empty ID — i.e. no designated 'current' keypair.
Source
Thrown at pkg/nodemodel/nodeupconfigbuilder.go:475
configServer.Servers = append(configServer.Servers, baseURL.String())
}
return configServer
}
func loadCertificates(keysets map[string]*fi.Keyset, name string, config *nodeup.Config, includeKeypairID bool) error {
keyset := keysets[name]
if keyset == nil {
return fmt.Errorf("key %q not found", name)
}
certificates, err := keyset.ToCertificateBytes()
if err != nil {
return fmt.Errorf("failed to read %q certificates: %w", name, err)
}
config.CAs[name] = string(certificates)
if includeKeypairID {
if keyset.Primary == nil || keyset.Primary.Id == "" {
return fmt.Errorf("key %q did not have primary id set", name)
}
config.KeypairIDs[name] = keyset.Primary.Id
}
return nil
}
// buildWarmPoolImages returns a list of container images that should be pre-pulled during instance pre-initialization
func (n *nodeUpConfigBuilder) buildWarmPoolImages(ig *kops.InstanceGroup) []string {
if ig == nil || ig.Spec.Role.HasControlPlane() {
return nil
}
images := map[string]bool{}
// Add component and addon images that impact startup time
// TODO: Exclude images that only run on control-plane nodes in a generic way
desiredImagePrefixes := []string{
// Ignore images hosted in private ECR repositories as containerd cannot actually pull theseView on GitHub (pinned to 4c8573c808)
Solutions
- Re-elect/recreate a primary: run `kops update cluster --yes` so kOps elects the newest keypair as primary, then retry.
- Use `kops get keypairs <name>` to inspect items; if none is marked primary, promote one (`kops promote keypair` / keyset rotation commands).
- If rotation left the keyset inconsistent, complete the rotation (issue/rotate/deregister cycle per kOps keypair rotation docs).
- Restore the primary pointer from the state-store backup if it was accidentally deleted.
Example fix
// before: keyset has items but no primary kops get keypairs kubernetes-ca # no item marked primary // after kops update cluster mycluster.k8s.local --yes # elects newest keypair as primary
Defensive patterns
Strategy: try-catch
Validate before calling
ks := keysets[name]
if ks != nil && includeKeypairID && (ks.Primary == nil || ks.Primary.Id == "") {
return fmt.Errorf("keyset %q has no primary keypair; run kops update cluster or promote a keypair", name)
} Type guard
func hasPrimary(ks *fi.Keyset) bool {
return ks != nil && ks.Primary != nil && ks.Primary.Id != ""
} Try / catch
if err := loadCertificates(keysets, name, config, true); err != nil {
if strings.Contains(err.Error(), "did not have primary id set") {
// no primary elected: re-run update or promote keypair before retry
return fmt.Errorf("keyset %q missing primary (%w); run 'kops update cluster --yes' or 'kops promote keypair'", name, err)
}
return err
} Prevention
- Complete keypair rotations fully (issue, promote, deregister) instead of stopping mid-cycle
- Check `kops get keypairs <name>` shows exactly one item marked primary before node bootstrap
- Never delete the primary keypair item directly; create a new one and promote it first
- Re-run `kops update cluster --yes` after any manual keystore surgery to restore primary election
When it happens
Trigger: BuildConfig -> loadCertificates with includeKeypairID=true on a keyset whose Primary field is nil or whose Primary.Id is an empty string: a keyset whose primary was never elected, a keyset whose primary was rotated/removed leaving no primary, or a keyset constructed programmatically/tests where Primary was not set.
Common situations: Keypair rotation interrupted mid-way leaving no elected primary; manually deleting the primary keypair item so only older items remain; clusters migrated between kOps versions where the primary-ID marker was not yet written; state store sync races where the primary pointer object was deleted.
Related errors
- did not find keypair %s for %s
- key %q not found
- missing keypairID for signer %s
- no keypair with id %s for %s
- creating keypair for %s: %v
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/ef78b70ab1c6ff8d.
Report an issue: GitHub.