{"record":{"id":"2df9d22d382126e4","repo":"hyperledger/fabric","slug":"invalid-pem-block","errorCode":null,"errorMessage":"invalid PEM block","messagePattern":"invalid PEM block","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"orderer/consensus/smartbft/consenter.go","lineNumber":330,"sourceCode":"\n// TargetChannel extracts the channel from the given proto.Message.\n// Returns an empty string on failure.\nfunc (c *Consenter) TargetChannel(message proto.Message) string {\n\tswitch req := message.(type) {\n\tcase *ab.ConsensusRequest:\n\t\treturn req.Channel\n\tcase *ab.SubmitRequest:\n\t\treturn req.Channel\n\tdefault:\n\t\treturn \"\"\n\t}\n}\n\nfunc pemToDER(pemBytes []byte, id uint64, certType string, logger *flogging.FabricLogger) ([]byte, error) {\n\tbl, _ := pem.Decode(pemBytes)\n\tif bl == nil {\n\t\tlogger.Errorf(\"Rejecting PEM block of %s TLS cert for node %d, offending PEM is: %s\", certType, id, string(pemBytes))\n\t\treturn nil, errors.Errorf(\"invalid PEM block\")\n\t}\n\treturn bl.Bytes, nil\n}\n\nfunc (c *Consenter) detectSelfID(consenters []*cb.Consenter) (uint64, error) {\n\tthisNodeCertAsDER, err := pemToDER(c.Comm.NodeIdentity, 0, \"server\", c.Logger)\n\tif err != nil {\n\t\tc.Logger.Errorf(\"Failed to convert node identity certificate to DER: %s\", err)\n\t\treturn 0, err\n\t}\n\n\tvar serverCertificates []string\n\tfor _, cst := range consenters {\n\t\tserverCertificates = append(serverCertificates, string(cst.Identity))\n\n\t\tcertAsDER, err := pemToDER(cst.Identity, uint64(cst.Id), \"server\", c.Logger)\n\t\tif err != nil {\n\t\t\tc.Logger.Errorf(\"Failed to convert node identity certificate to DER: %s\", err)","sourceCodeStart":312,"sourceCodeEnd":348,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/consensus/smartbft/consenter.go#L312-L348","documentation":"pemToDER decodes a PEM block (server or cluster TLS cert of a consenter) to raw DER bytes so detectSelfID can match the local node against the channel's consenter list. If pem.Decode fails, this error is returned and detectSelfID/remoteNodesFromConfigBlock abort, preventing cluster setup for that channel.","triggerScenarios":"A consenter's TLS certificate bytes — from the node's own Comm.NodeIdentity or from a config block's consenter TLS_Certs — are not decodable PEM: empty cert, DER-only cert, or malformed/extra text in the metadata of the block.","commonSituations":"Orderer TLS material misconfigured (wrong file or DER format); a channel config built with malformed consenter TLS certs; certificate rotation replacing PEM certs with non-PEM; configtx.yaml pointing at key files instead of cert files.","solutions":["Ensure orderer.yaml General.TLS.Certificate and Cluster.ServerCertificate/Certificate point to valid PEM certificate files (not keys, not DER)","Convert any DER certs to PEM (openssl x509 -inform der -out cert.pem) and restart the orderer","Regenerate the channel config with configtxgen after fixing TLS cert paths in the profile so ConsenterMapping contains valid PEM","Check the log line 'Rejecting PEM block of %s TLS cert for node %d' to identify which node/cert is offending"],"exampleFix":"// before (orderer.yaml)\nGeneral:\n  TLS:\n    Certificate: /path/server.key   # key file, not a PEM cert\n\n// after\nGeneral:\n  TLS:\n    Certificate: /path/server.crt   # PEM-encoded certificate","handlingStrategy":"validation","validationCode":"// Validate all TLS cert files are PEM certificates before starting the orderer\nfor _, p := range []string{tlsCert, clusterServerCert, clusterClientCert} {\n    b, err := os.ReadFile(p)\n    if err != nil { return err }\n    blk, _ := pem.Decode(b)\n    if blk == nil {\n        return fmt.Errorf(\"%s is not a valid PEM certificate\", p)\n    }\n    if _, err := x509.ParseCertificate(blk.Bytes); err != nil { return err }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Point TLS config entries at certificate files, never private keys","Use consistent PEM encoding across all cluster nodes' certs","Regenerate channel config after any TLS cert change","Run a preflight PEM check script in deployment automation"],"tags":["fabric","tls","pem","cluster","consensus"],"backgroundTag":"invalid-pem-certificate","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"}