{"record":{"id":"747972f89107936c","repo":"kubernetes/kops","slug":"no-certificate-provided","errorCode":null,"errorMessage":"no certificate provided","messagePattern":"no certificate provided","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/ca.go","lineNumber":201,"sourceCode":"}\n\n// NewKeyset creates a Keyset.\nfunc NewKeyset(cert *pki.Certificate, privateKey *pki.PrivateKey) (*Keyset, error) {\n\tkeyset := &Keyset{\n\t\tItems: map[string]*KeysetItem{},\n\t}\n\t_, err := keyset.AddItem(cert, privateKey, true)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn keyset, nil\n}\n\n// AddItem adds an item to the keyset\nfunc (k *Keyset) AddItem(cert *pki.Certificate, privateKey *pki.PrivateKey, primary bool) (item *KeysetItem, err error) {\n\tif cert == nil {\n\t\treturn item, fmt.Errorf(\"no certificate provided\")\n\t}\n\tif privateKey == nil && primary {\n\t\treturn item, fmt.Errorf(\"private key not provided for primary item\")\n\t}\n\n\tif !primary && k.Primary == nil {\n\t\treturn item, fmt.Errorf(\"cannot add secondary item when no existing primary item\")\n\t}\n\n\thighestId := big.NewInt(0)\n\tfor id := range k.Items {\n\t\titemId, ok := big.NewInt(0).SetString(id, 10)\n\t\tif ok && highestId.Cmp(itemId) < 0 {\n\t\t\thighestId = itemId\n\t\t}\n\t}\n\n\t// Make sure any subsequently created items will have ids that compare higher.","sourceCodeStart":183,"sourceCodeEnd":219,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/ca.go#L183-L219","documentation":"Keyset.AddItem adds a certificate/private key pair as a KeysetItem. It rejects a nil cert with the plain error 'no certificate provided' before any other validation, because every keyset item is defined by its certificate.","triggerScenarios":"NewKeyset -> Keyset.AddItem with cert == nil — the caller passed no certificate while adding to the keyset (privateKey may be present but cert is mandatory).","commonSituations":"Programmatic callers (provisioning code, tests, tooling that builds keysets) passing a parsed private key but a nil certificate — e.g. cert parsing failed upstream and the nil result was passed through unchecked.","solutions":["Fix the caller to load/parse the certificate before AddItem; check the parse error that yielded nil.","Ensure the cert file/resource exists and is valid PEM (openssl x509 -in cert.pem -noout).","If privateKey is passed and primary is true, also supply privateKey — but resolve the nil cert first as it fails earliest.","Wrap cert parsing to fail fast instead of forwarding nil into AddItem."],"exampleFix":"// before\ncert, err := pki.ParsePEMCertificate(data) // err ignored, cert==nil\nitem, err := keyset.AddItem(cert, priv, true)\n\n// after\ncert, err := pki.ParsePEMCertificate(data)\nif err != nil {\n  return nil, fmt.Errorf(\"parsing certificate: %w\", err)\n}\nif cert == nil {\n  return nil, fmt.Errorf(\"parsed certificate is nil\")\n}\nitem, err := keyset.AddItem(cert, priv, true)","handlingStrategy":"validation","validationCode":"function assertCertPresent(cert: Certificate | null | undefined, source: string): Certificate {\n  if (cert == null) throw new Error(\"certificate missing for keyset item from \" + source)\n  return cert\n}\nkeyset.addItem(assertCertPresent(maybeCert, \"ca-bundle\"), priv, true)","typeGuard":"function isCert(v: Certificate | null | undefined): v is Certificate {\n  return v != null\n}","tryCatchPattern":"try {\n  keyset.addItem(cert, priv, true)\n} catch (e) {\n  if (/no certificate provided/.test(e.message)) {\n    console.error(\"caller passed nil cert — check upstream parse error\")\n  }\n  throw e\n}","preventionTips":["Always check the error from cert parsing before passing results to AddItem.","Fail fast on nil certs at call-site boundaries.","Verify PEM files exist and parse (openssl x509) before provisioning.","Include cert source path in caller errors to speed debugging."],"tags":["pki","keyset","validation"],"backgroundTag":"missing-certificate","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"}