{"record":{"id":"d22cc1812e0f9531","repo":"slackhq/nebula","slug":"errrootexpired","errorCode":"ErrRootExpired","errorMessage":"root certificate is expired","messagePattern":"root certificate is expired","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"cert/errors.go","lineNumber":10,"sourceCode":"package cert\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n)\n\nvar (\n\tErrBadFormat                  = errors.New(\"bad wire format\")\n\tErrRootExpired                = errors.New(\"root certificate is expired\")\n\tErrExpired                    = errors.New(\"certificate is expired\")\n\tErrNotCA                      = errors.New(\"certificate is not a CA\")\n\tErrNotSelfSigned              = errors.New(\"certificate is not self-signed\")\n\tErrBlockListed                = errors.New(\"certificate is in the block list\")\n\tErrFingerprintMismatch        = errors.New(\"certificate fingerprint did not match\")\n\tErrSignatureMismatch          = errors.New(\"certificate signature did not match\")\n\tErrInvalidPublicKey           = errors.New(\"invalid public key\")\n\tErrInvalidPrivateKey          = errors.New(\"invalid private key\")\n\tErrPublicPrivateCurveMismatch = errors.New(\"public key does not match private key curve\")\n\tErrPublicPrivateKeyMismatch   = errors.New(\"public key and private key are not a pair\")\n\tErrPrivateKeyEncrypted        = errors.New(\"private key must be decrypted\")\n\tErrCaNotFound                 = errors.New(\"could not find ca for the certificate\")\n\tErrUnknownVersion             = errors.New(\"certificate version unrecognized\")\n\tErrCertPubkeyPresent          = errors.New(\"certificate has unexpected pubkey present\")\n\tErrCurveMismatch              = errors.New(\"certificate curve does not match CA\")\n\n\tErrInvalidPEMBlock                   = errors.New(\"input did not contain a valid PEM encoded block\")\n\tErrInvalidPEMCertificateBanner       = errors.New(\"bytes did not contain a proper certificate banner\")","sourceCodeStart":1,"sourceCodeEnd":28,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/cert/errors.go#L1-L28","documentation":"ErrRootExpired means the signing (root/CA) certificate's NotAfter time has passed relative to the `now` supplied to verify. The chain itself may be structurally valid, but trust is refused because the signer can no longer validate new chains.","triggerScenarios":"CAPool.verify (cert/ca_pool.go:225) returns this when signer.Certificate.Expired(now) is true — i.e., VerifyCertificate/VerifyCachedCertificate is called with a certificate whose selected CA signer's expiry is before the current time.","commonSituations":"A long-lived deployment whose CA cert aged past NotAfter without rotation; system clock skew (machine timezone/clock far off) making a still-valid CA look expired; reusing old test fixtures with fixed dates.","solutions":["Issue/rotate a new CA certificate and redistribute the updated ca.crt to all nodes.","Verify the local clock (date/NTP) — skew can make a valid CA appear expired.","Re-sign the leaf certificate with a still-valid CA.","Regenerate test pools with certs whose NotAfter covers the test run time."],"exampleFix":"// before\npool := cert.NewCAPoolFromBytes(caPem) // old expired CA\nvalid, err := pool.VerifyCertificate(cert)\n\n// after\ncaPem = fetchRotatedCA() // deploy renewed CA\npool := cert.NewCAPoolFromBytes(caPem)\nvalid, err := pool.VerifyCertificate(cert)","handlingStrategy":"try-catch","validationCode":"now := time.Now()\nfor _, ca := range pool.CAs {\n    if ca.Certificate.Expired(now) {\n        log.Warn(\"CA %s expired at %v — rotate it\", ca.Certificate.Name(), now)\n    }\n}","typeGuard":"func isSignerUsable(signer *cert.CachedCertificate, now time.Time) bool {\n    return signer != nil && !signer.Certificate.Expired(now)\n}","tryCatchPattern":"s, err := pool.VerifyCertificate(c, fp, \"\")\nif errors.Is(err, cert.ErrRootExpired) {\n    return fmt.Errorf(\"CA expired — deploy a renewed ca.crt (rotation required)\")\n}","preventionTips":["Monitor CA NotAfter dates and rotate well before expiry.","Run NTP/clock sync on all nodes.","Alert on pool.CAs entries close to expiry during startup checks."],"tags":["certificate","expiry","pkix"],"backgroundTag":"certificate-expired","analyzedSha":"dd8f660c0ac37903ec4080ca4d3c861ba9342ceb","analyzedAt":"2026-09-03T11:13:55.444Z","contentChangedAt":"2026-09-03T11:13:55.444Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}