hyperledger/fabric · error

cannot enable application capabilities without orderer suppo

Error message

cannot enable application capabilities without orderer support first

What it means

Same ordering rule as channel capabilities, applied to the application group: application capabilities may only be enabled after the orderer group already carries a capability entry. preValidate rejects a config where ApplicationGroup.Values[CapabilitiesKey] exists but the Orderer group's Values lack CapabilitiesKey, protecting older orderers from app-level config they cannot understand.

Source

Thrown at common/channelconfig/bundle.go:250

func preValidate(config *cb.Config) error {
	if config == nil {
		return errors.New("channelconfig Config cannot be nil")
	}

	if config.ChannelGroup == nil {
		return errors.New("config must contain a channel group")
	}

	if og, ok := config.ChannelGroup.Groups[OrdererGroupKey]; ok {
		if _, ok := og.Values[CapabilitiesKey]; !ok {
			if _, ok := config.ChannelGroup.Values[CapabilitiesKey]; ok {
				return errors.New("cannot enable channel capabilities without orderer support first")
			}

			if ag, ok := config.ChannelGroup.Groups[ApplicationGroupKey]; ok {
				if _, ok := ag.Values[CapabilitiesKey]; ok {
					return errors.New("cannot enable application capabilities without orderer support first")
				}
			}
		}
	}

	return nil
}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Submit an update enabling the capability in the Orderer group first, then enable the application capability in a second update
  2. Set Orderer: Capabilities in configtx.yaml to a version >= the application capability's requirement and regenerate
  3. Verify with configtxlator that groups.Orderer.values.Capabilities exists in the current config before crafting the app-capability delta

Example fix

// before
delta.Groups["Application"].Values["Capabilities"] = appCaps // rejected: no orderer caps

// after
og := delta.Groups["Orderer"]
og.Values["Capabilities"] = ordererCaps // step 1: enable orderer capability first
delta.Groups["Application"].Values["Capabilities"] = appCaps // step 2: then app capability
Defensive patterns

Strategy: validation

Validate before calling

func appCapsAllowed(cfg *cb.Config) bool {
    if cfg.ChannelGroup == nil { return true }
    ag, hasApp := cfg.ChannelGroup.Groups["Application"]
    _, hasAppCaps := map[string]*cb.ConfigValue{}, false
    if hasApp && ag.Values != nil {
        _, hasAppCaps = ag.Values["Capabilities"]
    }
    if !hasAppCaps { return true }
    og, ok := cfg.ChannelGroup.Groups["Orderer"]
    return ok && og.Values != nil && og.Values["Capabilities"] != nil
}

Try / catch

if err := updateChannelConfig(cfg); err != nil {
    if strings.Contains(err.Error(), "cannot enable application capabilities") {
        return fmt.Errorf("submit orderer-group capability update before application capability")
    }
    return err
}

Prevention

When it happens

Trigger: A config update adds an application capability (e.g. V1_3/V2_0) under config.ChannelGroup.Groups[ApplicationGroupKey].Values while Groups[OrdererGroupKey].Values contains no CapabilitiesKey — e.g. one-shot upgrade generated by configtxgen with only Application.Capabilities set.

Common situations: Upgrading application channels during a v1.x→v2.x migration and skipping the orderer-group step; configtx.yaml where Channel/Application capabilities are set but Orderer capabilities are commented out; tooling that copies application config into a new channel without orderer capabilities.

Related errors


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