{"record":{"id":"2466cf9df3dbde01","repo":"kubernetes/kops","slug":"missing-keypairid-for-signer-s","errorCode":null,"errorMessage":"missing keypairID for signer %s","messagePattern":"missing keypairID for signer (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/nodeup/nodetasks/issue_cert.go","lineNumber":222,"sourceCode":"\tcertificate *pki.Certificate\n\tkey         *pki.PrivateKey\n}\n\n// FindPrimaryKeypair implements pki.Keystore\nfunc (s staticKeystore) FindPrimaryKeypair(ctx context.Context, name string) (*pki.Certificate, *pki.PrivateKey, error) {\n\tif name != s.keyset {\n\t\treturn nil, nil, fmt.Errorf(\"wrong signer: expected %q got %q\", s.keyset, name)\n\t}\n\treturn s.certificate, s.key, nil\n}\n\nfunc newStaticKeystore(ctx context.Context, signer string, keypairID string, keystore fi.KeystoreReader) (pki.Keystore, error) {\n\tif signer == \"\" {\n\t\treturn nil, nil\n\t}\n\n\tif keypairID == \"\" {\n\t\treturn nil, fmt.Errorf(\"missing keypairID for signer %s\", signer)\n\t}\n\n\tkeyset, err := keystore.FindKeyset(ctx, signer)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"reading keyset for %s: %v\", signer, err)\n\t}\n\tif keyset == nil {\n\t\treturn nil, fmt.Errorf(\"keyset %q not found\", signer)\n\t}\n\n\titem := keyset.Items[keypairID]\n\tif item == nil {\n\t\treturn nil, fmt.Errorf(\"no keypair with id %s for %s\", keypairID, signer)\n\t}\n\n\treturn &staticKeystore{\n\t\tkeyset:      signer,\n\t\tcertificate: item.Certificate,","sourceCodeStart":204,"sourceCodeEnd":240,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/nodeup/nodetasks/issue_cert.go#L204-L240","documentation":"newStaticKeystore builds a pinned keystore for a signer, but a signer name was supplied with an empty keypairID, so there is no way to pin a specific keypair. The function refuses to construct a keystore in that state.","triggerScenarios":"Run() of the IssueCert task calls newStaticKeystore(ctx, signer, keypairID, keystore) with Signer set but KeypairID empty (task never recorded which keypair to use).","commonSituations":"Cluster created before keypair IDs were tracked, or task store lost the keypairID after an upgrade/restore; cert task built programmatically without setting KeypairID.","solutions":["Ensure the IssueCert task's KeypairID is populated from the keyset's primary item","Re-run kops upgrade/apply so the keypair ID is persisted into the task","If legacy, re-issue the certificate so a keypair ID is selected","Check that the cluster state store is intact and not missing keyset metadata"],"exampleFix":"// before\nissueCertTask.Signer = fi.String(\"kubernetes-ca\") // KeypairID left nil\n// after\nissueCertTask.KeypairID = fi.String(primaryKeypairID) // from keyset.Primary.ID","handlingStrategy":"validation","validationCode":"if signer != \"\" && keypairID == \"\" {\n  return fmt.Errorf(\"signer %s set but keypairID missing; run kops update cluster to persist it\", signer)\n}","typeGuard":null,"tryCatchPattern":"ks, err := newStaticKeystore(ctx, signer, keypairID, keystore)\nif err != nil && strings.HasPrefix(err.Error(), \"missing keypairID\") {\n  // fall back to resolving the keyset's primary item id, then retry\n}","preventionTips":["Always persist KeypairID when creating IssueCert tasks","Run kops upgrade after major version migrations","Don't hand-edit task state in the state store"],"tags":["nodeup","pki","keypair"],"backgroundTag":"missing-keypair-id","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"}