hyperledger/fabric · error
enrollment certificate should be a certificate, got a %s ins
Error message
enrollment certificate should be a certificate, got a %s instead
What it means
After successfully PEM-decoding the enrollment certificate, validateEnrollmentCertificate checks that the block type is exactly 'CERTIFICATE'. If a different PEM type (e.g. a private key, CSR, or public key) was supplied as the identity, this error reports the actual (lowercased) type found.
Source
Thrown at cmd/common/signer/signer.go:87
}
if err := validateEnrollmentCertificate(b); err != nil {
return nil, err
}
sId := &msp.SerializedIdentity{
Mspid: mspID,
IdBytes: b,
}
return protoutil.MarshalOrPanic(sId), nil
}
func validateEnrollmentCertificate(b []byte) error {
bl, _ := pem.Decode(b)
if bl == nil {
return errors.Errorf("enrollment certificate isn't a valid PEM block")
}
if bl.Type != "CERTIFICATE" {
return errors.Errorf("enrollment certificate should be a certificate, got a %s instead", strings.ToLower(bl.Type))
}
if _, err := x509.ParseCertificate(bl.Bytes); err != nil {
return errors.Errorf("enrollment certificate is not a valid x509 certificate: %v", err)
}
return nil
}
func (si *Signer) Sign(msg []byte) ([]byte, error) {
switch key := si.key.(type) {
// Fabric only supports ECDSA and ed25519 at the moment.
case *ecdsa.PrivateKey:
digest := util.ComputeSHA256(msg)
return signECDSA(si.key.(*ecdsa.PrivateKey), digest)
case ed25519.PrivateKey:
return ed25519.Sign(si.key.(ed25519.PrivateKey), msg), nil
default:
return nil, errors.Errorf("found unknown private key type (%T) in msg signing", key)View on GitHub (pinned to 2736b63f8f)
Solutions
- Set identity to the file containing '-----BEGIN CERTIFICATE-----' and key to the private key file
- Swap the identity and key values in config if they were mixed up
- Split a combined PEM file and use only the CERTIFICATE block as identity
Example fix
// before (config.yaml) signer: identity: /path/to/key.pem key: /path/to/cert.pem // after signer: identity: /path/to/cert.pem key: /path/to/key.pem
Defensive patterns
Strategy: validation
Validate before calling
blk, _ := pem.Decode(b)
if blk == nil || blk.Type != "CERTIFICATE" {
return fmt.Errorf("expected CERTIFICATE, got %v", blk)
} Type guard
func isCertificateBlock(b []byte) bool {
blk, _ := pem.Decode(b)
return blk != nil && blk.Type == "CERTIFICATE"
} Try / catch
if err := validateEnrollmentCertificate(b); err != nil {
if strings.Contains(err.Error(), "got a") {
return fmt.Errorf("identity file has wrong PEM type: %w", err)
}
return err
} Prevention
- Keep cert and key in separate, clearly named files
- Don't concatenate key+cert into the identity file
- Verify headers: identity must begin with BEGIN CERTIFICATE
When it happens
Trigger: Pointing signer.identity at the private key file (BEGIN PRIVATE KEY / BEGIN EC PRIVATE KEY), a CSR (BEGIN CERTIFICATE REQUEST), or a public key (BEGIN PUBLIC KEY) instead of the enrollment certificate.
Common situations: Swapped identity/key paths in config.yaml; concatenating key+cert and parsing picks the wrong block; using an admin's CSR instead of the issued cert; fetching the wrong file from a crypto-material directory.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- enrollment certificate isn't a valid PEM block
- enrollment certificate is not a valid x509 certificate: %v
- failed to decode PEM block from %s
- failed to add ca-file PEM to cert pool
- failed to PEM decode identity bytes: %s
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/f3feff55da52a876.
Report an issue: GitHub.