{"record":{"id":"7c0a629b4fd6ec8d","repo":"hyperledger/fabric","slug":"cannot-load-server-cert-for-consenter-s-d-s","errorCode":null,"errorMessage":"cannot load server cert for consenter %s:%d: %s","messagePattern":"cannot load server cert for consenter (.+?):(.+?): (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/channelconfig/util.go","lineNumber":325,"sourceCode":"\t}\n\treturn cc, nil\n}\n\n// MarshalEtcdRaftMetadata serializes etcd RAFT metadata.\nfunc MarshalEtcdRaftMetadata(md *etcdraft.ConfigMetadata) ([]byte, error) {\n\tcopyMd := proto.Clone(md).(*etcdraft.ConfigMetadata)\n\tfor _, c := range copyMd.Consenters {\n\t\t// Expect the user to set the config value for client/server certs to the\n\t\t// path where they are persisted locally, then load these files to memory.\n\t\tclientCert, err := os.ReadFile(string(c.GetClientTlsCert()))\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"cannot load client cert for consenter %s:%d: %s\", c.GetHost(), c.GetPort(), err)\n\t\t}\n\t\tc.ClientTlsCert = clientCert\n\n\t\tserverCert, err := os.ReadFile(string(c.GetServerTlsCert()))\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"cannot load server cert for consenter %s:%d: %s\", c.GetHost(), c.GetPort(), err)\n\t\t}\n\t\tc.ServerTlsCert = serverCert\n\t}\n\treturn proto.Marshal(copyMd)\n}\n\n// MarshalBFTOptions serializes smartbft options.\nfunc MarshalBFTOptions(op *smartbft.Options) ([]byte, error) {\n\tif copyMd, ok := proto.Clone(op).(*smartbft.Options); ok {\n\t\treturn proto.Marshal(copyMd)\n\t} else {\n\t\treturn nil, errors.New(\"consenter options type mismatch\")\n\t}\n}\n","sourceCodeStart":307,"sourceCodeEnd":340,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/common/channelconfig/util.go#L307-L340","documentation":"MarshalEtcdRaftMetadata also reads each consenter's server TLS cert from its local path and inlines the bytes. This error wraps the os.ReadFile failure for the server TLS cert, naming the consenter host:port and the OS error. Same mechanics as the client-cert error but for ServerTlsCert.","triggerScenarios":"NewOrdererGroup invoked with etcdraft metadata where a consenter's ServerTlsCert path is missing, unreadable, or points to a directory — reached only after the client cert read succeeded.","commonSituations":"Client and server cert paths mixed up in configtx.yaml; only one of the two certs copied into a container image; cert file deleted/moved during rotation; typo in the server cert filename.","solutions":["Correct the server_tls_cert path in the consenter config to an existing, readable file.","Verify both ClientTLSCert and ServerTLSCert point to their intended files (they are often the same cert but distinct paths are validated separately).","Mount/copy the server certs into the container or distribution package alongside the client certs.","Check permissions and read the wrapped OS error for the precise failure (ENOENT vs EACCES)."],"exampleFix":"// before\nClientTLSCert: ./tls/server.crt\nServerTLSCert: ./tls/clint.crt   # typo\n// after\nClientTLSCert: ./tls/server.crt\nServerTLSCert: ./tls/server.crt","handlingStrategy":"validation","validationCode":"func validateServerCerts(md *etcdraft.ConfigMetadata) error {\n\tfor _, c := range md.Consenters {\n\t\tif _, err := os.Stat(string(c.GetServerTlsCert())); err != nil {\n\t\t\treturn fmt.Errorf(\"server cert %q for %s:%d unreadable: %w\", c.GetServerTlsCert(), c.GetHost(), c.GetPort(), err)\n\t\t}\n\t}\n\treturn nil\n}","typeGuard":null,"tryCatchPattern":"// errors are returned, not panicked; wrap the call\nmd, err := channelconfig.MarshalEtcdRaftMetadata(metadata)\nif err != nil {\n\tvar pe *fs.PathError\n\tif errors.As(err, &pe) { /* fix server cert path */ }\n\treturn fmt.Errorf(\"raft metadata: %w\", err)\n}","preventionTips":["Validate both ClientTLSCert and ServerTLSCert paths — they are read independently","Copy both certs into container images during build","Use consistent, absolute paths generated from one template to avoid typos","Re-check paths after cert rotation or directory moves"],"tags":["hyperledger-fabric","etcdraft","tls","file-io"],"backgroundTag":"tls-cert-file-not-found","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"}