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.

Solutions

  1. Regenerate the config update ensuring every consenter has host, port, and client/server TLS certs set
  2. Validate the metadata with VerifyConfigMetadata before submitting the update transaction
  3. 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

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


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

Appendix: 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)