hyperledger/fabric · error
illegal orderer config update detected: endpoints of org %s
Error message
illegal orderer config update detected: endpoints of org %s are missing
What it means
This error comes from Hyperledger Fabric's channelconfig bundle validation (ValidateNew in common/channelconfig/bundle.go). When a config update attempts to switch a channel's consensus type to BFT (the new V3 capability is enabled while the old one was not), every orderer organization in the new config must declare endpoints. If an orderer org in the proposed config has an empty Endpoints() list, the update is rejected because BFT consensus requires peers to know each orderer's address.
Source
Thrown at common/channelconfig/bundle.go:102
if !ok {
return errors.New("current config has orderer section, but new config does not")
}
// Prevent consensus-type migration when channel capabilities ConsensusTypeMigration is disabled
if !b.channelConfig.Capabilities().ConsensusTypeMigration() {
if oc.ConsensusType() != noc.ConsensusType() {
return errors.Errorf("attempted to change consensus type from %s to %s",
oc.ConsensusType(), noc.ConsensusType())
}
}
// When we move to capability V3_0 we insist on per Org endpoints for every org
isOldV3 := b.ChannelConfig().Capabilities().ConsensusTypeBFT()
isNewV3 := nb.ChannelConfig().Capabilities().ConsensusTypeBFT()
if !isOldV3 && isNewV3 {
for _, org := range noc.Organizations() {
if len(org.Endpoints()) == 0 {
return errors.Errorf("illegal orderer config update detected: endpoints of org %s are missing", org.Name())
}
}
}
for orgName, org := range oc.Organizations() {
norg, ok := noc.Organizations()[orgName]
if !ok {
continue
}
mspID := org.MSPID()
if mspID != norg.MSPID() {
return errors.Errorf("orderer org %s attempted to change MSP ID from %s to %s", orgName, mspID, norg.MSPID())
}
}
}
if ac, ok := b.ApplicationConfig(); ok {
nac, ok := nb.ApplicationConfig()View on GitHub (pinned to 2736b63f8f)
Solutions
- Add the 'Endpoints' key to the Orderer section of every orderer organization in the new config (e.g. Endpoints: - orderer.example.com:7050) and regenerate the config.
- Run configtxlator to decode the proposed config and verify each org under channel->group->Orderer->groups has a value under 'Orderer->values->Endpoints'.
- Verify channel capabilities: if you are enabling V3_0/BFT capability in the same update, ensure the config diff includes endpoints for ALL orderer orgs before submitting.
- If the org genuinely needs no orderer endpoints, remove it from the Orderer group's Organizations rather than leaving it empty.
Example fix
// before (configtx.yaml, orderer org without endpoints in Orderer section)
Orderer:
Organizations:
- &OrdererOrg
Name: OrdererOrg
ID: OrdererMSP
MSPDir: msp
// after
Orderer:
Organizations:
- &OrdererOrg
Name: OrdererOrg
ID: OrdererMSP
MSPDir: msp
OrdererEndpoints:
- orderer.example.com:7050 Defensive patterns
Strategy: validation
Validate before calling
// Before submitting a config update, decode the new config and check orderer org endpoints
func validateOrdererEndpoints(newConfig *cb.Config) error {
ordererGroup, ok := newConfig.Groups["Orderer"]
if !ok {
return nil
}
for orgName, orgGroup := range ordererGroup.Groups {
epVal, ok := orgGroup.Values["Endpoints"]
if !ok || epVal == nil {
return fmt.Errorf("org %s has no Endpoints value; BFT capability requires it", orgName)
}
}
return nil
} Type guard
func hasEndpoints(orgGroup *cb.ConfigGroup) bool {
v, ok := orgGroup.Values["Endpoints"]
return ok && v != nil
} Try / catch
// Fabric returns errors from Update/Validate rather than panics
if err := configtxManager.ProposeConfigUpdate(env); err != nil {
if strings.Contains(err.Error(), "endpoints of org") {
// fail fast: fix configtx and regenerate update, do not retry
return fmt.Errorf("config update rejected: %w", err)
}
return err
} Prevention
- Always define OrdererEndpoints in configtx.yaml for every orderer org used in the Orderer group
- Diff current vs proposed config JSON with configtxlator before submitting any update
- When enabling V3_0/BFT capability, inventory all orderer orgs first and confirm each has endpoints
- Use configtxgen's validate mode to lint profiles before generating update transactions
When it happens
Trigger: A channel config update transaction (via configtxgen/configtxlator or the orderer's configuration update path) where the new config enables ConsensusTypeBFT capability (e.g. moving capabilities from V2.x to V3.0 / BFT) while at least one OrdererGroup organization's config lacks the 'Endpoints' key in its Orderer section (org.Endpoints() returns empty).
Common situations: Upgrading a network to Fabric 3.0 / BFT consensus (e.g. switching etcdraft->smartbft or enabling V3_0 channel capability); generating a new channel config where an orderer org was defined in the 'Organizations' list of the Orderer group without an 'Endpoints' field in its Orderer section; copying org definitions from the Consortiums section (which has no endpoints) into the orderer group.
Related errors
- orderer org %s attempted to change MSP ID from %s to %s
- current config has application section, but new config does
- application org %s attempted to change MSP ID from %s to %s
- current config has consortiums section, but new config does
- no orderer section in channel config for channel [%s].
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/0d95b192d0b9ce88.
Report an issue: GitHub.