hyperledger/fabric · critical

etcdraft options have not been provided

Error message

etcdraft options have not been provided

What it means

HandleChain (orderer/consensus/etcdraft/consenter.go:126) requires etcdraft Options (TickInterval, ElectionTick, HeartbeatTick, MaxInflightMsgs, SnapshotInterval) to be present in the channel's consensus metadata. If the unmarshaled ConfigMetadata has no Options field, the chain cannot be configured and this error is returned. It indicates an incomplete etcdraft configuration in the channel config.

Source

Thrown at orderer/consensus/etcdraft/consenter.go:126

		if crypto.CertificatesWithSamePublicKey(thisNodeCertAsDER, certAsDER) == nil {
			return nodeID, nil
		}
	}

	c.Logger.Warning("Could not find", string(c.Cert), "among", serverCertificates)
	return 0, cluster.ErrNotInChannel
}

// HandleChain returns a new Chain instance or an error upon failure
func (c *Consenter) HandleChain(support consensus.ConsenterSupport, metadata *common.Metadata) (consensus.Chain, error) {
	m := &etcdraft.ConfigMetadata{}
	if err := proto.Unmarshal(support.SharedConfig().ConsensusMetadata(), m); err != nil {
		return nil, errors.Wrap(err, "failed to unmarshal consensus metadata")
	}

	if m.GetOptions() == nil {
		return nil, errors.New("etcdraft options have not been provided")
	}

	isMigration := (metadata == nil || len(metadata.GetValue()) == 0) && (support.Height() > 1)
	if isMigration {
		c.Logger.Debugf("Block metadata is nil at block height=%d, it is consensus-type migration", support.Height())
	}

	// determine raft replica set mapping for each node to its id
	// for newly started chain we need to read and initialize raft
	// metadata by creating mapping between conseter and its id.
	// In case chain has been restarted we restore raft metadata
	// information from the recently committed block meta data
	// field.
	blockMetadata, err := ReadBlockMetadata(metadata, m)
	if err != nil {
		return nil, errors.Wrapf(err, "failed to read Raft metadata")
	}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Regenerate the genesis/config metadata including Options (TickInterval, ElectionTick, HeartbeatTick, MaxInflightMsgs, SnapshotInterval) via configtxgen
  2. Add the missing Options block to the channel config and resubmit via config update if channel already exists
  3. Use a Fabric version-matched sample configtx.yaml Orderer.EtcdRaft.Options section as template

Example fix

// before
ConfigMetadata{Consenters: [...]} // Options omitted
// after
ConfigMetadata{Consenters: [...], Options: &etcdraft.Options{TickInterval: "500ms", ElectionTick: 10, HeartbeatTick: 1, MaxInflightMsgs: 256, SnapshotInterval: 4194304}}
Defensive patterns

Strategy: validation

Validate before calling

m := &etcdraft.ConfigMetadata{}
if err := proto.Unmarshal(raw, m); err != nil { return err }
if m.GetOptions() == nil {
    return errors.New("ConfigMetadata.Options is required (TickInterval, ticks, SnapshotInterval, MaxInflightMsgs)")
}

Type guard

func hasRaftOptions(m *etcdraft.ConfigMetadata) bool {
    o := m.GetOptions()
    return o != nil && o.GetTickInterval() != "" && o.GetElectionTick() > 0 && o.GetHeartbeatTick() > 0
}

Prevention

When it happens

Trigger: A channel is configured with consensus type etcdraft but its ConfigMetadata proto lacks the Options field (nil Options), detected during orderer chain startup.

Common situations: Hand-built genesis config that populated Consenters but omitted Options; a migration to etcdraft whose metadata template was incomplete; tooling that zeroed Options when rewriting metadata.

Related errors


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