{"record":{"id":"54affaaed6bafd86","repo":"hyperledger/fabric","slug":"server-root-ca-cert-is-nil","errorCode":null,"errorMessage":"server root CA cert is nil","messagePattern":"server root CA cert is nil","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"orderer/common/cluster/connectionsmgr.go","lineNumber":44,"sourceCode":"}\n\nfunc (cbc ConnectionsCache) Remove(key string) {\n\tdelete(cbc, key)\n}\n\nfunc (cbc ConnectionsCache) Size() int {\n\treturn len(cbc)\n}\n\ntype ConnectionsMgr struct {\n\tlock        sync.RWMutex\n\tConnections ConnectionsCache\n\tdialer      comm.ClientConfig\n}\n\nfunc (c *ConnectionsMgr) Connect(endpoint string, serverRootCACert [][]byte) (*grpc.ClientConn, error) {\n\tif serverRootCACert == nil {\n\t\treturn nil, errors.New(\"server root CA cert is nil\")\n\t}\n\n\tc.lock.Lock()\n\tconn, alreadyConnected := c.Connections.Lookup(endpoint)\n\tif alreadyConnected {\n\t\tc.lock.Unlock()\n\t\treturn conn, nil\n\t}\n\tdialer := c.dialer\n\tc.lock.Unlock()\n\n\tdialer.SecOpts.ServerRootCAs = serverRootCACert\n\tnewConn, err := dialer.Dial(endpoint)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tc.lock.Lock()","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/common/cluster/connectionsmgr.go#L26-L62","documentation":"ConnectionsMgr.Connect dials a remote orderer and requires the server's root CA certificate(s) to authenticate TLS. Passing a nil serverRootCACert slice means there is nothing to verify the server against, so Connect fails fast before dialing.","triggerScenarios":"Calling Connect(endpoint, nil), typically when the caller's channel config yielded no TLS CA certs (e.g. empty tls.rootCerts in the channel config or config not yet loaded).","commonSituations":"Channel config block not yet retrieved/parsed so rootCerts is empty; channel configured without TLS while the orderer cluster uses mutual TLS; a bug in config propagation leaving the cert field unset.","solutions":["Populate serverRootCACert with the channel's Orderer TLS root certs from the latest config block","Ensure the channel config (tls.rootCerts) is loaded before calling Connect","If TLS is disabled intentionally, configure the dialer/comm.ClientConfig accordingly instead of passing a nil CA"],"exampleFix":"// before\nconn, err := mgr.Connect(endpoint, nil)\n// after\nif len(tlsCACerts) == 0 {\n    return nil, errors.New(\"no TLS CA certs in channel config\")\n}\nconn, err := mgr.Connect(endpoint, tlsCACerts)","handlingStrategy":"validation","validationCode":"if len(serverRootCACert) == 0 {\n    return nil, fmt.Errorf(\"cannot connect: no server root CA certs available\")\n}\nconn, err := mgr.Connect(endpoint, serverRootCACert)","typeGuard":"func hasRootCACerts(certs [][]byte) bool {\n    return len(certs) > 0 && len(certs[0]) > 0\n}","tryCatchPattern":"conn, err := mgr.Connect(endpoint, caCerts)\nif err != nil {\n    if strings.Contains(err.Error(), \"root CA cert is nil\") {\n        return nil, fmt.Errorf(\"channel config missing TLS root certs: %w\", err)\n    }\n    return nil, err\n}","preventionTips":["Always read tls.rootCerts from the latest channel config before dialing","Fail fast at config-load time when TLS certs are absent","Validate channel config completeness after fetching config blocks"],"tags":["tls","configuration","grpc","missing-config"],"backgroundTag":"missing-tls-ca-cert","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"}