hyperledger/fabric · error
parsing tls server cert of %s:%d
Error message
parsing tls server cert of %s:%d
What it means
validateConsenterTLSCerts then parses the consenter's server TLS cert; failure is wrapped with 'parsing tls server cert of <host>:<port>'. As with the client cert, this indicates the server_tls_cert bytes in the etcdraft consenter config are not decodable PEM/DER X.509 data. The error surfaces during VerifyConfigMetadata or ValidateConsensusMetadata of the channel config.
Source
Thrown at orderer/consensus/etcdraft/util.go:329
Roots: tlsRoots,
Intermediates: tlsIntermediates,
KeyUsages: []x509.ExtKeyUsage{
x509.ExtKeyUsageClientAuth,
x509.ExtKeyUsageServerAuth,
},
}, nil
}
// validateConsenterTLSCerts decodes PEM cert, parses and validates it.
func validateConsenterTLSCerts(c *etcdraft.Consenter, opts x509.VerifyOptions, ignoreExpiration bool) error {
clientCert, err := parseCertificateFromBytes(c.GetClientTlsCert())
if err != nil {
return errors.Wrapf(err, "parsing tls client cert of %s:%d", c.GetHost(), c.GetPort())
}
serverCert, err := parseCertificateFromBytes(c.GetServerTlsCert())
if err != nil {
return errors.Wrapf(err, "parsing tls server cert of %s:%d", c.GetHost(), c.GetPort())
}
verify := func(certType string, cert *x509.Certificate, opts x509.VerifyOptions) error {
if _, err := cert.Verify(opts); err != nil {
if validationRes, ok := err.(x509.CertificateInvalidError); !ok || (!ignoreExpiration || validationRes.Reason != x509.Expired) {
return errors.Wrapf(err, "verifying tls %s cert with serial number %d", certType, cert.SerialNumber)
}
}
return nil
}
if err := verify("client", clientCert, opts); err != nil {
return err
}
if err := verify("server", serverCert, opts); err != nil {
return err
}
View on GitHub (pinned to 2736b63f8f)
Solutions
- Set the consenter's server_tls_cert to the base64-encoded tls/server.crt (-----BEGIN CERTIFICATE-----) and update channel config
- Verify the two cert fields aren't swapped: parse both with openssl x509 and compare with the node's actual TLS files
- Check the cert file wasn't truncated (should contain header, body, footer lines) and re-encode with base64 -w0
- Regenerate the node's TLS material and rebuild the config update transaction
Example fix
// before: base64 of key file server_tls_cert: "$(base64 orderer.example.com/tls/server.key)" // after server_tls_cert: "$(base64 orderer.example.com/tls/server.crt)"
Defensive patterns
Strategy: validation
Validate before calling
// validate each consenter's server TLS cert before config update
for _, c := range metadata.Consenters {
if err := validateTLSCertBytes(c.ServerTlsCert); err != nil {
return fmt.Errorf("consenter %s:%d has invalid server tls cert: %w", c.Host, c.Port, err)
}
} Type guard
func hasValidServerTLSCert(c *etcdraft.Consenter) bool {
block, _ := pem.Decode(c.GetServerTlsCert())
return block != nil && block.Type == "CERTIFICATE"
} Try / catch
if err := ValidateConsensusMetadata(m, l, nil); err != nil {
if strings.Contains(err.Error(), "parsing tls server cert of") {
return fmt.Errorf("a consenter's server_tls_cert is malformed: %w", err)
}
return err
} Prevention
- Fill server_tls_cert from the node's tls/server.crt only; never paste key material
- Double-check client/server cert fields are not transposed in configtx.yaml
- Verify cert PEM integrity (BEGIN/END lines intact) before encoding
- Automate consenter cert population from the node's crypto dir instead of manual copy
When it happens
Trigger: Channel config update for an etcdraft consenter whose GetServerTlsCert() is empty, non-PEM, or contains bytes that fail x509.ParseCertificate; the consenter is identified by host:port in the wrapped message.
Common situations: operator swapped the client and server cert fields; server_tls_cert contains the private key; cert pasted without proper base64 encoding; file truncated during copy into configtx.yaml.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- parsing tls client cert of %s:%d
- cannot load client cert for consenter %s:%d: %s
- cannot load server cert for consenter %s:%d: %s
- %s TLS certificate has invalid ASN1 structure %s
- parsing tls root certs
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/28d49972f3504f3e.
Report an issue: GitHub.