hyperledger/fabric · error

my consenter certificate

Error message

my consenter certificate %s is not a valid PEM

What it means

IsConsenterOfChannel decodes the consenter's own certificate with pem.Decode; if the result is nil the bytes are not a valid PEM block, and the error embeds the raw certificate bytes as a string. The library throws it because it cannot extract the DER certificate needed to compare against the consenters listed in the channel's etcdraft ConfigMetadata.

Solutions

  1. Point the consenter certificate configuration at a PEM-encoded X.509 certificate file (-----BEGIN CERTIFICATE-----), not a key or DER file
  2. Regenerate the consenter certificate from the org CA and pass it as PEM (openssl x509 -in cert.crt -out cert.pem if needed)
  3. Verify the file/env providing the cert is actually mounted and non-empty at orderer startup

Example fix

// before: raw DER or key material passed
conCert := ConsenterCertificate{ConsenterCertificate: derBytes}
// after: ensure PEM-encoded certificate
pemBytes, err := os.ReadFile("consenter-cert.pem") // contains -----BEGIN CERTIFICATE-----
if err != nil { return err }
conCert := ConsenterCertificate{ConsenterCertificate: pemBytes}
Defensive patterns

Strategy: validation

Validate before calling

func isPEMCertificate(b []byte) bool {
    block, _ := pem.Decode(b)
    if block == nil || block.Type != "CERTIFICATE" { return false }
    _, err := x509.ParseCertificate(block.Bytes)
    return err == nil
}

Type guard

func hasValidConsenterCert(c ConsenterCertificate) bool {
    return isPEMCertificate(c.ConsenterCertificate)
}

Prevention

When it happens

Trigger: ConsenterCertificate.ConsenterCertificate contains an empty slice, raw DER bytes without PEM armor, a private key file, or text/garbage instead of a PEM-encoded X.509 certificate.

Common situations: GeneralGenesisFile/TLS genesis material misconfigured so the consenter cert field points at a key or wrong file; certificate passed as base64 instead of PEM; empty env var or mount for the consenter certificate at orderer startup.

Understand the failure class

Related errors


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/ca93a78877165ba6. Report an issue: GitHub.

Appendix: source

Thrown at orderer/consensus/etcdraft/util.go:384

	if err != nil {
		return err
	}
	bundle, err := channelconfig.NewBundleFromEnvelope(envelopeConfig, conCert.CryptoProvider)
	if err != nil {
		return err
	}
	oc, exists := bundle.OrdererConfig()
	if !exists {
		return errors.New("no orderer config in bundle")
	}
	m := &etcdraft.ConfigMetadata{}
	if err := proto.Unmarshal(oc.ConsensusMetadata(), m); err != nil {
		return err
	}

	bl, _ := pem.Decode(conCert.ConsenterCertificate)
	if bl == nil {
		return errors.Errorf("my consenter certificate %s is not a valid PEM", string(conCert.ConsenterCertificate))
	}

	myCertDER := bl.Bytes

	var failedMatches []string
	for _, consenter := range m.GetConsenters() {
		candidateBlock, _ := pem.Decode(consenter.GetServerTlsCert())
		if candidateBlock == nil {
			return errors.Errorf("candidate server certificate %s is not a valid PEM", string(consenter.GetServerTlsCert()))
		}
		sameServerCertErr := crypto.CertificatesWithSamePublicKey(myCertDER, candidateBlock.Bytes)

		candidateBlock, _ = pem.Decode(consenter.GetClientTlsCert())
		if candidateBlock == nil {
			return errors.Errorf("candidate client certificate %s is not a valid PEM", string(consenter.GetClientTlsCert()))
		}
		sameClientCertErr := crypto.CertificatesWithSamePublicKey(myCertDER, candidateBlock.Bytes)

View on GitHub (pinned to 2736b63f8f)