{"record":{"id":"7513fef520dce276","repo":"hyperledger/fabric","slug":"verifying-tls-s-cert-with-serial-number-d","errorCode":null,"errorMessage":"verifying tls %s cert with serial number %d","messagePattern":"verifying tls (.+?) cert with serial number (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"orderer/consensus/etcdraft/util.go","lineNumber":335,"sourceCode":"\t}, nil\n}\n\n// validateConsenterTLSCerts decodes PEM cert, parses and validates it.\nfunc validateConsenterTLSCerts(c *etcdraft.Consenter, opts x509.VerifyOptions, ignoreExpiration bool) error {\n\tclientCert, err := parseCertificateFromBytes(c.GetClientTlsCert())\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"parsing tls client cert of %s:%d\", c.GetHost(), c.GetPort())\n\t}\n\n\tserverCert, err := parseCertificateFromBytes(c.GetServerTlsCert())\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"parsing tls server cert of %s:%d\", c.GetHost(), c.GetPort())\n\t}\n\n\tverify := func(certType string, cert *x509.Certificate, opts x509.VerifyOptions) error {\n\t\tif _, err := cert.Verify(opts); err != nil {\n\t\t\tif validationRes, ok := err.(x509.CertificateInvalidError); !ok || (!ignoreExpiration || validationRes.Reason != x509.Expired) {\n\t\t\t\treturn errors.Wrapf(err, \"verifying tls %s cert with serial number %d\", certType, cert.SerialNumber)\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}\n\n\tif err := verify(\"client\", clientCert, opts); err != nil {\n\t\treturn err\n\t}\n\tif err := verify(\"server\", serverCert, opts); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\n// ConsenterCertificate denotes a TLS certificate of a consenter\ntype ConsenterCertificate struct {\n\tConsenterCertificate []byte","sourceCodeStart":317,"sourceCodeEnd":353,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/consensus/etcdraft/util.go#L317-L353","documentation":"In etcdraft/util.go, before joining or verifying consenter TLS certificates, each peer's client/server certificate is verified against the channel's root CAs. If x509 Certificate.Verify fails with anything other than an (optionally ignored) expiry error, it is wrapped with the cert type (client/server), the serial number, and the underlying x509 error. The library throws it because a TLS cert that cannot chain to the channel trust anchors makes the consenter unusable for secure communication.","triggerScenarios":"Calling channels/consenter verification (e.g. cluster verification in etcdraft) where a consenter's TLS client or server certificate fails Verify against the supplied VerifyOptions: unknown CA, wrong key usage, expired/not-yet-valid cert, or hostname mismatch.","commonSituations":"Orderer TLS certificates rotated with new intermediate CAs not listed in the channel config's TLS root CAs; cert generated for a different hostname than the consenter's configured host:port; system clock skew making a valid cert appear expired; mixing Org1-issued certs into an Org2 consenter config.","solutions":["Add the issuing CA of the failing cert (serial shown in the message) to the channel's TLS root CAs (and intermediates if chaining requires it) via a channel config update","Regenerate the consenter TLS certificate from the organization's MSP CA so it chains to the configured roots","Ensure KeyUsage/ExtKeyUsage on the cert matches its role (serverAuth/server, clientAuth/client)","Fix host clock skew (NTP) or reissue the cert if it is expired or not yet valid"],"exampleFix":"// before: consenter TLS cert signed by CA absent from channel config\n// after: configtx update adding the CA\n// channelconfig: Orderer.Organizations.<MSP>.TLSRootCerts += new-ca.pem\n// then regenerate consenter cert:\n// fabric-ca-client gencsr --tls.keyfiles tls.key --csr.hosts orderer.example.com","handlingStrategy":"validation","validationCode":"func validateTLSCert(certPEM, certType string, roots *x509.CertPool, serverName string) error {\n    block, _ := pem.Decode([]byte(certPEM))\n    if block == nil { return errors.New(\"not PEM\") }\n    cert, err := x509.ParseCertificate(block.Bytes)\n    if err != nil { return err }\n    opts := x509.VerifyOptions{Roots: roots, DNSName: serverName}\n    if certType == \"client\" { opts.KeyUsages = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth} }\n    _, err = cert.Verify(opts)\n    return err\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep channel TLS root/intermediate CA lists in sync with the CA that issues orderer certs","Use SANs matching the consenter's configured host:port when issuing certs","Check cert expiry and rotate before they lapse","Enable NTP on all orderer nodes to avoid clock-skew validation failures"],"tags":["tls","x509","hyperledger-fabric","certificate-verification"],"backgroundTag":"tls-certificate-verification-failed","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}