hyperledger/fabric · error

global orderer endpoints exist, but can not be used with V3_

Error message

global orderer endpoints exist, but can not be used with V3_0 capability: %v

What it means

Starting with the V3_0 channel capability, per-channel orderer endpoints are used instead of the legacy global Orderer.Addresses list. If configtx.yaml defines global addresses while V3_0 is enabled, NewOrdererGroup rejects the config because those endpoints would be ignored/misplaced in a V3_0 channel. The error lists the offending addresses.

Source

Thrown at internal/configtxgen/encoder/encoder.go:190

		channelGroup.Groups[channelconfig.ConsortiumsGroupKey], err = NewConsortiumsGroup(conf.Consortiums)
		if err != nil {
			return nil, errors.Wrap(err, "could not create consortiums group")
		}
	}

	channelGroup.ModPolicy = channelconfig.AdminsPolicyKey
	return channelGroup, nil
}

// NewOrdererGroup returns the orderer component of the channel configuration.  It defines parameters of the ordering service
// about how large blocks should be, how frequently they should be emitted, etc. as well as the organizations of the ordering network.
// It sets the mod_policy of all elements to "Admins".  This group is always present in any channel configuration.
func NewOrdererGroup(conf *genesisconfig.Orderer, channelCapabilities map[string]bool) (*cb.ConfigGroup, error) {
	if conf.OrdererType == "BFT" && !channelCapabilities["V3_0"] {
		return nil, errors.Errorf("orderer type BFT must be used with V3_0 channel capability: %v", channelCapabilities)
	}
	if len(conf.Addresses) > 0 && channelCapabilities["V3_0"] {
		return nil, errors.Errorf("global orderer endpoints exist, but can not be used with V3_0 capability: %v", conf.Addresses)
	}

	ordererGroup := protoutil.NewConfigGroup()
	if err := AddOrdererPolicies(ordererGroup, conf.Policies, channelconfig.AdminsPolicyKey); err != nil {
		return nil, errors.Wrapf(err, "error adding policies to orderer group")
	}
	addValue(ordererGroup, channelconfig.BatchSizeValue(
		conf.BatchSize.MaxMessageCount,
		conf.BatchSize.AbsoluteMaxBytes,
		conf.BatchSize.PreferredMaxBytes,
	), channelconfig.AdminsPolicyKey)
	addValue(ordererGroup, channelconfig.BatchTimeoutValue(conf.BatchTimeout.String()), channelconfig.AdminsPolicyKey)
	addValue(ordererGroup, channelconfig.ChannelRestrictionsValue(conf.MaxChannels), channelconfig.AdminsPolicyKey)

	if len(conf.Capabilities) > 0 {
		addValue(ordererGroup, channelconfig.CapabilitiesValue(conf.Capabilities), channelconfig.AdminsPolicyKey)
	}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Remove the Addresses: entry under the Orderer section in configtx.yaml; V3_0 takes orderer endpoints from the Orderers config value / per-consenter configuration
  2. If you need shared endpoints, set them per consenter (TLS certs/host/port in the consenters list) rather than globally
  3. Regenerate the channel config/genesis block after removing the addresses

Example fix

# before
Orderer:
    OrdererType: etcdraft
    Addresses:
        - orderer.example.com:7050
# after
Orderer:
    OrdererType: etcdraft
    # Addresses removed for V3_0; endpoints come from consenter config
    EtcdRaft:
        Consenters:
            - Host: orderer.example.com
              Port: 7050
Defensive patterns

Strategy: validation

Validate before calling

func validateNoGlobalAddresses(conf *genesisconfig.Orderer, caps map[string]bool) error {
    if len(conf.Addresses) > 0 && caps["V3_0"] {
        return fmt.Errorf("remove Orderer.Addresses %v when V3_0 capability is enabled", conf.Addresses)
    }
    return nil
}

Type guard

func hasGlobalOrdererAddresses(conf *genesisconfig.Orderer) bool { return len(conf.Addresses) > 0 }

Try / catch

group, err := encoder.NewOrdererGroup(conf, caps)
if err != nil && strings.Contains(err.Error(), "global orderer endpoints") {
    return fmt.Errorf("delete the Addresses: section under Orderer in configtx.yaml for V3_0: %w", err)
}

Prevention

When it happens

Trigger: Calling NewOrdererGroup/NewChannelGroup with a genesisconfig.Orderer whose Addresses slice is non-empty AND channelCapabilities["V3_0"] is true — i.e. Orderer.Addresses set in configtx.yaml together with the V3_0 channel capability.

Common situations: Upgrading an old configtx.yaml to V3_0 capabilities (e.g. when moving to BFT) without removing the deprecated Orderer.Addresses section, or copying profiles from Fabric 2.x docs into a V3_0 profile.

Related errors


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