hyperledger/fabric · error

cannot marshal metadata for orderer type %s: %s

Error message

cannot marshal metadata for orderer type %s: %s

What it means

For etcdraft orderers, NewOrdererGroup serializes conf.EtcdRaft (consenters, tick interval, election/heartbeat timeouts) into the config group metadata via channelconfig.MarshalEtcdRaftMetadata. If that proto cannot be marshaled or validated, the encoder fails with this message naming the etcdraft orderer type and the underlying error.

Source

Thrown at internal/configtxgen/encoder/encoder.go:216

		conf.BatchSize.MaxMessageCount,
		conf.BatchSize.AbsoluteMaxBytes,
		conf.BatchSize.PreferredMaxBytes,
	), channelconfig.AdminsPolicyKey)
	addValue(ordererGroup, channelconfig.BatchTimeoutValue(conf.BatchTimeout.String()), channelconfig.AdminsPolicyKey)
	addValue(ordererGroup, channelconfig.ChannelRestrictionsValue(conf.MaxChannels), channelconfig.AdminsPolicyKey)

	if len(conf.Capabilities) > 0 {
		addValue(ordererGroup, channelconfig.CapabilitiesValue(conf.Capabilities), channelconfig.AdminsPolicyKey)
	}

	var consensusMetadata []byte
	var err error

	switch conf.OrdererType {
	case ConsensusTypeSolo:
	case ConsensusTypeEtcdRaft:
		if consensusMetadata, err = channelconfig.MarshalEtcdRaftMetadata(conf.EtcdRaft); err != nil {
			return nil, errors.Errorf("cannot marshal metadata for orderer type %s: %s", ConsensusTypeEtcdRaft, err)
		}
	case ConsensusTypeBFT:
		consenterProtos, err := consenterProtosFromConfig(conf.ConsenterMapping)
		if err != nil {
			return nil, errors.Errorf("cannot load consenter config for orderer type %s: %s", ConsensusTypeBFT, err)
		}
		addValue(ordererGroup, channelconfig.OrderersValue(consenterProtos), channelconfig.AdminsPolicyKey)
		if consensusMetadata, err = channelconfig.MarshalBFTOptions(conf.SmartBFT); err != nil {
			return nil, errors.Errorf("consenter options read failed with error %s for orderer type %s", err, ConsensusTypeBFT)
		}
		// Force leader rotation to be turned off
		conf.SmartBFT.LeaderRotation = smartbft.Options_ROTATION_OFF
		// Overwrite policy manually by computing it from the consenters
		policies.EncodeBFTBlockVerificationPolicy(consenterProtos, ordererGroup)
	default:
		return nil, errors.Errorf("unknown orderer type: %s", conf.OrdererType)
	}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Check the underlying error after the colon — it identifies which field failed validation
  2. Verify every consenter's ClientTLSCert/ServerTLSCert paths exist and contain valid PEM
  3. Ensure EtcdRaft settings (TickInterval, ElectionTick, HeartbeatTick, MaxInflightBlocks) are set per the sample configtx.yaml
  4. Regenerate the genesis block after fixing the EtcdRaft section

Example fix

# before
EtcdRaft:
    Consenters:
        - Host: orderer.example.com
          Port: 7050
          # missing certs
# after
EtcdRaft:
    Consenters:
        - Host: orderer.example.com
          Port: 7050
          ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt
          ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt
Defensive patterns

Strategy: validation

Validate before calling

func validateEtcdRaft(conf *genesisconfig.EtcdRaft) error {
    if len(conf.Consenters) == 0 { return errors.New("etcdraft requires at least one consenter") }
    for _, c := range conf.Consenters {
        if _, err := os.ReadFile(c.ClientTLSCert); err != nil { return fmt.Errorf("client cert: %w", err) }
        if _, err := os.ReadFile(c.ServerTLSCert); err != nil { return fmt.Errorf("server cert: %w", err) }
    }
    return nil
}

Type guard

func isEtcdRaft(conf *genesisconfig.Orderer) bool { return conf.OrdererType == "etcdraft" }

Try / catch

group, err := encoder.NewOrdererGroup(conf, caps)
if err != nil {
    if strings.Contains(err.Error(), "cannot marshal metadata") {
        return fmt.Errorf("fix EtcdRaft section (consenters/certs/ticks): %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling NewOrdererGroup/NewChannelGroup with OrdererType "etcdraft" where conf.EtcdRaft is invalid — e.g. malformed TLS cert paths/contents in Consenters, unset required fields — causing MarshalEtcdRaftMetadata to error.

Common situations: TLS certificate paths in EtcdRaft.Consenters pointing to files that are unreadable or not valid PEM, empty Consenters list, or programmatically constructed genesisconfig with a nil/zero EtcdRaft struct.

Related errors


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