hyperledger/fabric · error
consenter options read failed with error
Error message
consenter options read failed with error %s for orderer type %s
What it means
For BFT orderers, after loading consenters the encoder marshals conf.SmartBFT (the smartbft.Options proto) into consensus metadata via channelconfig.MarshalBFTOptions. If those options are invalid or cannot be serialized, NewOrdererGroup returns this message embedding the marshal error and the BFT orderer type.
Solutions
- Read the embedded error after 'error' — it identifies which SmartBFT option failed
- Compare your SmartBFT block against the Fabric BFT sample configtx.yaml and fix field names/values
- If options are set programmatically, validate the smartbft.Options proto before calling the encoder
- Regenerate the genesis/channel config once options are corrected
Example fix
# before
SmartBFT:
RequestBatchMaxCount: "not-a-number"
# after
SmartBFT:
RequestBatchMaxCount: 100
RequestBatchMaxInterval: 50ms
LeaderRotation: 0 Defensive patterns
Strategy: validation
Validate before calling
func validateSmartBFTOptions(opts *smartbft.Options) error {
if opts == nil { return errors.New("SmartBFT options required for BFT orderer") }
if opts.RequestBatchMaxCount <= 0 { return errors.New("RequestBatchMaxCount must be positive") }
return nil
} Type guard
func hasSmartBFT(conf *genesisconfig.Orderer) bool { return conf.OrdererType == "BFT" && conf.SmartBFT != nil } Try / catch
group, err := encoder.NewOrdererGroup(conf, caps)
if err != nil && strings.Contains(err.Error(), "consenter options read failed") {
return fmt.Errorf("fix SmartBFT options block in configtx.yaml: %w", err)
} Prevention
- Copy the SmartBFT block verbatim from the Fabric BFT sample configtx.yaml
- Never reuse an etcdraft options block under OrdererType: BFT
- Keep numeric/time fields in the exact formats the sample uses (e.g. 50ms)
When it happens
Trigger: NewOrdererGroup/NewChannelGroup with OrdererType "BFT" where MarshalBFTOptions(conf.SmartBFT) fails — e.g. malformed/missing SmartBFT fields in configtx.yaml (request batch timeouts, leader rotation settings, incorrect numeric values).
Common situations: Hand-editing the SmartBFT section with wrong field names/types, leaving required options unset, or reusing an etcdraft profile body under a BFT OrdererType.
Related errors
- cannot load consenter config for orderer type
- orderer type BFT must be used with V3_0 channel capability
- bad config metadata option CollectTimeout
- bad config metadata option LeaderHeartbeatTimeout
- bad config metadata option ViewChangeResendInterval
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/ec6ef6005d66c12c.
Report an issue: GitHub.
Appendix: source
Thrown at internal/configtxgen/encoder/encoder.go:225
}
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)
}
addValue(ordererGroup, channelconfig.ConsensusTypeValue(conf.OrdererType, consensusMetadata), channelconfig.AdminsPolicyKey)
for _, org := range conf.Organizations {
var err error
ordererGroup.Groups[org.Name], err = NewOrdererOrgGroup(org, channelCapabilities)
if err != nil {
return nil, errors.Wrap(err, "failed to create orderer org")
}
}View on GitHub (pinned to 2736b63f8f)