hyperledger/fabric · error
nil consenter in metadata
Error message
nil consenter in metadata
What it means
While iterating over the consenters in ConfigMetadata to detect duplicates, MetadataHasDuplication finds a nil consenter entry and rejects the whole config update with this error. A nil consenter would have no TLS certificates and cannot participate in raft, so the metadata is invalid.
Source
Thrown at orderer/consensus/etcdraft/util.go:67
func ConsentersToMap(consenters []*etcdraft.Consenter) ConsentersMap {
set := map[string]struct{}{}
for _, c := range consenters {
set[string(c.GetClientTlsCert())] = struct{}{}
}
return set
}
// MetadataHasDuplication returns an error if the metadata has duplication of consenters.
// A duplication is defined by having a server or a client TLS certificate that is found
// in two different consenters, regardless of the type of certificate (client/server).
func MetadataHasDuplication(md *etcdraft.ConfigMetadata) error {
if md == nil {
return errors.New("nil metadata")
}
for _, consenter := range md.GetConsenters() {
if consenter == nil {
return errors.New("nil consenter in metadata")
}
}
seen := make(map[string]struct{})
for _, consenter := range md.GetConsenters() {
serverKey := string(consenter.GetServerTlsCert())
clientKey := string(consenter.GetClientTlsCert())
_, duplicateServerCert := seen[serverKey]
_, duplicateClientCert := seen[clientKey]
if duplicateServerCert || duplicateClientCert {
return errors.Errorf("duplicate consenter: server cert: %s, client cert: %s", serverKey, clientKey)
}
seen[serverKey] = struct{}{}
seen[clientKey] = struct{}{}
}
return nil
}View on GitHub (pinned to 2736b63f8f)
Solutions
- Regenerate the config update ensuring every consenter has host, port, and client/server TLS certs set
- Validate the metadata with VerifyConfigMetadata before submitting the update transaction
- Fix the generating code to never append nil/zero-value Consenter messages
Example fix
// before
metadata.Consenters = append(metadata.Consenters, &etcdraft.Consenter{})
// after
metadata.Consenters = append(metadata.Consenters, &etcdraft.Consenter{
Host: host, Port: port,
ServerTlsCert: serverCert, ClientTlsCert: clientCert,
}) Defensive patterns
Strategy: validation
Validate before calling
for i, c := range metadata.GetConsenters() {
if c == nil {
return fmt.Errorf("consenter %d is nil", i)
}
if c.GetHost() == "" || c.GetPort() == 0 || len(c.GetServerTlsCert()) == 0 || len(c.GetClientTlsCert()) == 0 {
return fmt.Errorf("consenter %d incomplete", i)
}
} Type guard
func isValidConsenter(c *etcdraft.Consenter) bool {
return c != nil && c.GetHost() != "" && c.GetPort() != 0 &&
len(c.GetServerTlsCert()) > 0 && len(c.GetClientTlsCert()) > 0
} Prevention
- Never append zero-value Consenter structs in config generators
- Validate metadata with VerifyConfigMetadata before submitting updates
- Round-trip marshal/unmarshal the metadata in tests
- Review generated channel-update JSON for empty consenter entries
When it happens
Trigger: A channel config update whose etcdraft metadata's consenter list contains a nil entry — usually from programmatically appending an unset *etcdraft.Consenter or a partially built protobuf message.
Common situations: Custom channel-creation/update scripts appending an empty consenter element; SDK/config generators producing a repeated field with one uninitialized entry; hand-edited JSON config converted to protobuf.
Related errors
- nil metadata
- duplicate consenter: server cert: %s, client cert: %s
- failed to unmarshal consensusType config update
- failed to extract envelope from the block
- nil Raft config metadata options
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/78755ac6d81c6fe0.
Report an issue: GitHub.