{"record":{"id":"ef78b70ab1c6ff8d","repo":"kubernetes/kops","slug":"key-q-did-not-have-primary-id-set","errorCode":null,"errorMessage":"key %q did not have primary id set","messagePattern":"key %q did not have primary id set","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/nodemodel/nodeupconfigbuilder.go","lineNumber":475,"sourceCode":"\t\tconfigServer.Servers = append(configServer.Servers, baseURL.String())\n\t}\n\n\treturn configServer\n}\n\nfunc loadCertificates(keysets map[string]*fi.Keyset, name string, config *nodeup.Config, includeKeypairID bool) error {\n\tkeyset := keysets[name]\n\tif keyset == nil {\n\t\treturn fmt.Errorf(\"key %q not found\", name)\n\t}\n\tcertificates, err := keyset.ToCertificateBytes()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to read %q certificates: %w\", name, err)\n\t}\n\tconfig.CAs[name] = string(certificates)\n\tif includeKeypairID {\n\t\tif keyset.Primary == nil || keyset.Primary.Id == \"\" {\n\t\t\treturn fmt.Errorf(\"key %q did not have primary id set\", name)\n\t\t}\n\t\tconfig.KeypairIDs[name] = keyset.Primary.Id\n\t}\n\treturn nil\n}\n\n// buildWarmPoolImages returns a list of container images that should be pre-pulled during instance pre-initialization\nfunc (n *nodeUpConfigBuilder) buildWarmPoolImages(ig *kops.InstanceGroup) []string {\n\tif ig == nil || ig.Spec.Role.HasControlPlane() {\n\t\treturn nil\n\t}\n\n\timages := map[string]bool{}\n\n\t// Add component and addon images that impact startup time\n\t// TODO: Exclude images that only run on control-plane nodes in a generic way\n\tdesiredImagePrefixes := []string{\n\t\t// Ignore images hosted in private ECR repositories as containerd cannot actually pull these","sourceCodeStart":457,"sourceCodeEnd":493,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/nodemodel/nodeupconfigbuilder.go#L457-L493","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: keyset has items but no primary\nkops get keypairs kubernetes-ca  # no item marked primary\n// after\nkops update cluster mycluster.k8s.local --yes  # elects newest keypair as primary","handlingStrategy":"try-catch","validationCode":"ks := keysets[name]\nif ks != nil && includeKeypairID && (ks.Primary == nil || ks.Primary.Id == \"\") {\n    return fmt.Errorf(\"keyset %q has no primary keypair; run kops update cluster or promote a keypair\", name)\n}","typeGuard":"func hasPrimary(ks *fi.Keyset) bool {\n    return ks != nil && ks.Primary != nil && ks.Primary.Id != \"\"\n}","tryCatchPattern":"if err := loadCertificates(keysets, name, config, true); err != nil {\n    if strings.Contains(err.Error(), \"did not have primary id set\") {\n        // no primary elected: re-run update or promote keypair before retry\n        return fmt.Errorf(\"keyset %q missing primary (%w); run 'kops update cluster --yes' or 'kops promote keypair'\", name, err)\n    }\n    return err\n}","preventionTips":["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"],"tags":["pki","keypair","primary-id","rotation","nodeup"],"backgroundTag":"missing-primary-keypair","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}