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

  1. 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.
  2. Run configtxlator to decode the proposed config and verify each org under channel->group->Orderer->groups has a value under 'Orderer->values->Endpoints'.
  3. 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.
  4. 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

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


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