hyperledger/fabric · error
metadata has nil consenter
Error message
metadata has nil consenter
What it means
While iterating over the consenters, a nil entry in metadata.GetConsenters() is rejected: every consenter must carry host, port and TLS certs. This indicates malformed metadata rather than an invalid certificate (that produces a different wrapped error).
Source
Thrown at orderer/consensus/etcdraft/util.go:244
if metadata.GetOptions().GetElectionTick() <= metadata.GetOptions().GetHeartbeatTick() {
return errors.Errorf("ElectionTick (%d) must be greater than HeartbeatTick (%d)",
metadata.GetOptions().GetElectionTick(), metadata.GetOptions().GetHeartbeatTick())
}
if d, err := time.ParseDuration(metadata.GetOptions().GetTickInterval()); err != nil {
return errors.Errorf("failed to parse TickInterval (%s) to time duration: %s", metadata.GetOptions().GetTickInterval(), err)
} else if d == 0 {
return errors.Errorf("TickInterval cannot be zero")
}
if len(metadata.GetConsenters()) == 0 {
return errors.Errorf("empty consenter set")
}
// verifying certificates for being signed by CA, expiration is ignored
for _, consenter := range metadata.GetConsenters() {
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)
}View on GitHub (pinned to 2736b63f8f)
Solutions
- Remove nil entries and populate each Consenter with Host, Port, ServerTlsCert and ClientTlsCert.
- Check the code path that builds Consenters for accidental nil appends.
- Pre-validate the slice with a loop checking each element non-nil before calling VerifyConfigMetadata.
Example fix
// before
consenters = append(consenters, nilConsenterMaybe())
// after
if c := buildConsenter(); c != nil { consenters = append(consenters, c) } Defensive patterns
Strategy: type-guard
Validate before calling
for i, c := range metadata.GetConsenters() {
if c == nil {
return fmt.Errorf("consenter at index %d is nil", i)
}
} Type guard
func allConsentersPresent(m *etcdraft.ConfigMetadata) bool {
for _, c := range m.GetConsenters() {
if c == nil || c.GetHost() == "" || c.GetPort() == 0 {
return false
}
}
return len(m.GetConsenters()) > 0
} Try / catch
if err := VerifyConfigMetadata(meta, opts); err != nil {
if strings.Contains(err.Error(), "nil consenter") {
return errors.New("config-generation bug: nil entry in Consenters list")
}
return err
} Prevention
- Check for nil before appending to Consenters in generated code.
- Add unit tests asserting no nil elements in built ConfigMetadata.
- Validate host/port/certs are set on every consenter before submission.
When it happens
Trigger: A ConfigMetadata whose Consenters slice contains a nil element, typically from buggy config-generation code or partial protobuf decoding.
Common situations: Programmatically appending consenters and appending a nil pointer; proto decoded with a consenter message that is present but empty and represented as nil in the slice.
Related errors
- nil Raft config metadata
- empty consenter set
- config envelope is nil
- nil ledger instance
- Invalid signed proposal during channelless check policy with
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/4e8428f9b6c2e2d8.
Report an issue: GitHub.