{"record":{"id":"c706d92f919ab319","repo":"hyperledger/fabric","slug":"etcdraft-options-have-not-been-provided","errorCode":null,"errorMessage":"etcdraft options have not been provided","messagePattern":"etcdraft options have not been provided","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"orderer/consensus/etcdraft/consenter.go","lineNumber":126,"sourceCode":"\n\t\tif crypto.CertificatesWithSamePublicKey(thisNodeCertAsDER, certAsDER) == nil {\n\t\t\treturn nodeID, nil\n\t\t}\n\t}\n\n\tc.Logger.Warning(\"Could not find\", string(c.Cert), \"among\", serverCertificates)\n\treturn 0, cluster.ErrNotInChannel\n}\n\n// HandleChain returns a new Chain instance or an error upon failure\nfunc (c *Consenter) HandleChain(support consensus.ConsenterSupport, metadata *common.Metadata) (consensus.Chain, error) {\n\tm := &etcdraft.ConfigMetadata{}\n\tif err := proto.Unmarshal(support.SharedConfig().ConsensusMetadata(), m); err != nil {\n\t\treturn nil, errors.Wrap(err, \"failed to unmarshal consensus metadata\")\n\t}\n\n\tif m.GetOptions() == nil {\n\t\treturn nil, errors.New(\"etcdraft options have not been provided\")\n\t}\n\n\tisMigration := (metadata == nil || len(metadata.GetValue()) == 0) && (support.Height() > 1)\n\tif isMigration {\n\t\tc.Logger.Debugf(\"Block metadata is nil at block height=%d, it is consensus-type migration\", support.Height())\n\t}\n\n\t// determine raft replica set mapping for each node to its id\n\t// for newly started chain we need to read and initialize raft\n\t// metadata by creating mapping between conseter and its id.\n\t// In case chain has been restarted we restore raft metadata\n\t// information from the recently committed block meta data\n\t// field.\n\tblockMetadata, err := ReadBlockMetadata(metadata, m)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"failed to read Raft metadata\")\n\t}\n","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/consensus/etcdraft/consenter.go#L108-L144","documentation":"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.","triggerScenarios":"A channel is configured with consensus type etcdraft but its ConfigMetadata proto lacks the Options field (nil Options), detected during orderer chain startup.","commonSituations":"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.","solutions":["Regenerate the genesis/config metadata including Options (TickInterval, ElectionTick, HeartbeatTick, MaxInflightMsgs, SnapshotInterval) via configtxgen","Add the missing Options block to the channel config and resubmit via config update if channel already exists","Use a Fabric version-matched sample configtx.yaml Orderer.EtcdRaft.Options section as template"],"exampleFix":"// before\nConfigMetadata{Consenters: [...]} // Options omitted\n// after\nConfigMetadata{Consenters: [...], Options: &etcdraft.Options{TickInterval: \"500ms\", ElectionTick: 10, HeartbeatTick: 1, MaxInflightMsgs: 256, SnapshotInterval: 4194304}}","handlingStrategy":"validation","validationCode":"m := &etcdraft.ConfigMetadata{}\nif err := proto.Unmarshal(raw, m); err != nil { return err }\nif m.GetOptions() == nil {\n    return errors.New(\"ConfigMetadata.Options is required (TickInterval, ticks, SnapshotInterval, MaxInflightMsgs)\")\n}","typeGuard":"func hasRaftOptions(m *etcdraft.ConfigMetadata) bool {\n    o := m.GetOptions()\n    return o != nil && o.GetTickInterval() != \"\" && o.GetElectionTick() > 0 && o.GetHeartbeatTick() > 0\n}","tryCatchPattern":null,"preventionTips":["Start from the sample Orderer.EtcdRaft section in configtx.yaml","Never strip Options when regenerating metadata","Test genesis blocks with configtxgen before deploying"],"tags":["raft","configuration","options","orderer-startup"],"backgroundTag":"missing-etcdraft-options","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}