{"record":{"id":"74c84f80a185231b","repo":"hyperledger/fabric","slug":"cannot-load-client-cert-for-consenter-s-d-s-74c84f","errorCode":null,"errorMessage":"cannot load client cert for consenter %s:%d: %s","messagePattern":"cannot load client cert for consenter (.+?):(.+?): (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/configtxgen/encoder/encoder.go","lineNumber":263,"sourceCode":"\tordererGroup.ModPolicy = channelconfig.AdminsPolicyKey\n\treturn ordererGroup, nil\n}\n\nfunc consenterProtosFromConfig(consenterMapping []*genesisconfig.Consenter) ([]*cb.Consenter, error) {\n\tvar consenterProtos []*cb.Consenter\n\tfor _, consenter := range consenterMapping {\n\t\tc := &cb.Consenter{\n\t\t\tId:    consenter.ID,\n\t\t\tHost:  consenter.Host,\n\t\t\tPort:  consenter.Port,\n\t\t\tMspId: consenter.MSPID,\n\t\t}\n\t\t// Expect the user to set the config value for client/server certs or identity to the\n\t\t// path where they are persisted locally, then load these files to memory.\n\t\tif consenter.ClientTLSCert != \"\" {\n\t\t\tclientCert, err := os.ReadFile(consenter.ClientTLSCert)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"cannot load client cert for consenter %s:%d: %s\", c.GetHost(), c.GetPort(), err)\n\t\t\t}\n\t\t\tc.ClientTlsCert = clientCert\n\t\t}\n\n\t\tif consenter.ServerTLSCert != \"\" {\n\t\t\tserverCert, err := os.ReadFile(consenter.ServerTLSCert)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"cannot load server cert for consenter %s:%d: %s\", c.GetHost(), c.GetPort(), err)\n\t\t\t}\n\t\t\tc.ServerTlsCert = serverCert\n\t\t}\n\n\t\tif consenter.Identity != \"\" {\n\t\t\tidentity, err := os.ReadFile(consenter.Identity)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"cannot load identity for consenter %s:%d: %s\", c.GetHost(), c.GetPort(), err)\n\t\t\t}\n\t\t\tc.Identity = identity","sourceCodeStart":245,"sourceCodeEnd":281,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/internal/configtxgen/encoder/encoder.go#L245-L281","documentation":"consenterProtosFromConfig reads each consenter's ClientTLSCert file from disk (os.ReadFile) and embeds the bytes into the consenter proto. When the file cannot be read — missing path, permission denied, directory instead of file — it returns this error identifying the consenter by host:port. This occurs while building BFT orderer configuration.","triggerScenarios":"NewOrdererGroup (OrdererType BFT) → consenterProtosFromConfig with a ConsenterMapping entry whose ClientTLSCert path is set but unreadable: nonexistent file, no read permission, or wrong working directory for relative paths.","commonSituations":"Running configtxgen from a different directory than the crypto material expects, cert files deleted or never generated, or copy-pasted paths from another machine (e.g. Windows paths on Linux).","solutions":["Check the embedded OS error: 'no such file' → fix the path; 'permission denied' → fix file permissions (chmod 644)","Verify the ClientTLSCert path for the consenter at the reported host:port exists (ls the file)","Run configtxgen from the directory where relative paths in configtx.yaml resolve, or convert to absolute paths","Regenerate TLS certs if the crypto material is absent"],"exampleFix":"# before\nConsenterMapping:\n    - Host: orderer.example.com\n      Port: 7050\n      ClientTLSCert: tls/client.crt   # does not exist\n# after\nConsenterMapping:\n    - Host: orderer.example.com\n      Port: 7050\n      ClientTLSCert: /abs/path/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt","handlingStrategy":"validation","validationCode":"func checkClientCertReadable(path string) error {\n    b, err := os.ReadFile(path)\n    if err != nil { return err }\n    if !bytes.Contains(b, []byte(\"-----BEGIN CERTIFICATE-----\")) {\n        return errors.New(\"file is not a PEM certificate\")\n    }\n    return nil\n}","typeGuard":"func clientCertExists(consenter *genesisconfig.Consenter) bool {\n    if consenter.ClientTLSCert == \"\" { return true }\n    _, err := os.Stat(consenter.ClientTLSCert); return err == nil\n}","tryCatchPattern":"group, err := encoder.NewOrdererGroup(conf, caps)\nif err != nil && strings.Contains(err.Error(), \"cannot load client cert\") {\n    return fmt.Errorf(\"fix ClientTLSCert path for the named consenter: %w\", err)\n}","preventionTips":["Stat every consenter cert path before invoking configtxgen","Generate TLS certs for all nodes before building BFT configuration","Use absolute paths in CI so relative-path assumptions never break"],"tags":["tls","filesystem","hyperledger-fabric","bft"],"backgroundTag":"certificate-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"}