hyperledger/fabric · error
no PEM data found in cert[% x]
Error message
no PEM data found in cert[% x]
What it means
parseCertificateFromBytes decodes a consenter's TLS cert with pem.Decode; this error means the byte slice contained no PEM block, so no x509 certificate can be parsed. The message includes the raw hex of the offending bytes for diagnosis.
Solutions
- Inspect the hex in the message to see what bytes were actually provided (empty vs non-PEM).
- Ensure ServerTlsCert and ClientTlsCert are PEM-encoded certificates (BEGIN CERTIFICATE/END CERTIFICATE) of the orderer's TLS keypair.
- Re-encode the cert file as PEM (openssl x509 -in cert.der -out cert.pem) or fix the file path in the orderer config.
- Regenerate the channel config update with corrected consenter certificates.
Example fix
// before: raw/der bytes
consenter.ServerTlsCert = derBytes
// after: PEM-encoded
tsCertPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
consenter.ServerTlsCert = tsCertPEM Defensive patterns
Strategy: validation
Validate before calling
func isPEMCert(b []byte) bool {
block, _ := pem.Decode(b)
return block != nil && block.Type == "CERTIFICATE"
}
// apply to each consenter
if !isPEMCert(consenter.GetServerTlsCert()) || !isPEMCert(consenter.GetClientTlsCert()) {
return errors.New("consenter TLS certs must be PEM-encoded certificates")
} Type guard
func hasPEMCerts(c *etcdraft.Consenter) bool {
return isPEMCert(c.GetServerTlsCert()) && isPEMCert(c.GetClientTlsCert())
} Try / catch
if err := VerifyConfigMetadata(meta, opts); err != nil {
if strings.Contains(err.Error(), "no PEM data found") {
return fmt.Errorf("replace consenter TLS cert with PEM file: %v", err)
}
return err
} Prevention
- Always point config at PEM files (-----BEGIN CERTIFICATE-----) for TLS certs.
- Never base64-encode certs again after storing them in YAML.
- Verify cert files are non-empty on the orderer host before generating config.
- Use openssl x509 -in cert.pem -noout to confirm certs parse before embedding.
When it happens
Trigger: validateConsenterTLSCerts called with a consenter whose ServerTlsCert or ClientTlsCert is empty, base64-encoded-only data, a DER binary without PEM armor, or random garbage.
Common situations: configtx.yaml pointing at the wrong file for TLS certs; pasting a certificate without BEGIN/END lines; certs stored base64 in YAML and encoded again; empty cert file on the orderer; mixing up signing cert with TLS cert in channel config.
Related errors
- could not decode the PEM structure
- failed to add ca-file PEM to cert pool
- failed to PEM decode identity bytes
- my consenter certificate
- No suitable BFT consenter for Raft consenter
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/c0932b952a80b4fa.
Report an issue: GitHub.
Appendix: source
Thrown at orderer/consensus/etcdraft/util.go:261
if consenter == nil {
return errors.Errorf("metadata has nil consenter")
}
if err := validateConsenterTLSCerts(consenter, verifyOpts, true); err != nil {
return errors.WithMessagef(err, "consenter %s:%d has invalid certificate", consenter.GetHost(), consenter.GetPort())
}
}
if err := MetadataHasDuplication(metadata); err != nil {
return err
}
return nil
}
func parseCertificateFromBytes(cert []byte) (*x509.Certificate, error) {
pemBlock, _ := pem.Decode(cert)
if pemBlock == nil {
return &x509.Certificate{}, errors.Errorf("no PEM data found in cert[% x]", cert)
}
certificate, err := x509.ParseCertificate(pemBlock.Bytes)
if err != nil {
return nil, errors.Errorf("%s TLS certificate has invalid ASN1 structure %s", err, string(pemBlock.Bytes))
}
return certificate, nil
}
func parseCertificateListFromBytes(certs [][]byte) ([]*x509.Certificate, error) {
var certificateList []*x509.Certificate
for _, cert := range certs {
certificate, err := parseCertificateFromBytes(cert)
if err != nil {
return certificateList, err
}View on GitHub (pinned to 2736b63f8f)