hyperledger/fabric · error

config must contain a channel group

Error message

config must contain a channel group

What it means

This error means the config transaction submitted to NewBundle had a nil ChannelGroup. preValidate in common/channelconfig/bundle.go runs first on every new bundle and requires a channel-level config group to exist, since all channel configuration (capabilities, orderer/application/consortium sub-groups) hangs off it. Without it there is nothing to validate or build a bundle from.

Source

Thrown at common/channelconfig/bundle.go:239

	configtxManager, err := configtx.NewValidatorImpl(channelID, config, RootGroupKey, policyManager)
	if err != nil {
		return nil, errors.Wrap(err, "initializing configtx manager failed")
	}

	return &Bundle{
		policyManager:   policyManager,
		channelConfig:   channelConfig,
		configtxManager: configtxManager,
	}, nil
}

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. Regenerate the config from configtxgen/configtxlator so a ChannelGroup is present at the root of cb.Config
  2. If decoding a ConfigEnvelope, verify the envelope is complete and unmarshals fully (check err from proto.Unmarshal)
  3. In tests, populate cfg.ChannelGroup = &cb.ConfigGroup{} (plus required values) before calling NewBundle
  4. Validate the update with `configtxlator proto_decode` before submitting it to the orderer

Example fix

// before
cfg := &cb.Config{Values: map[string]*cb.ConfigValue{}}
bundle, err := channelconfig.NewBundle(cfg, bccsp) // panics into: config must contain a channel group

// after
cfg := &cb.Config{
    ChannelGroup: &cb.ConfigGroup{
        Values: map[string]*cb.ConfigValue{},
        Groups: map[string]*cb.ConfigGroup{},
    },
}
bundle, err := channelconfig.NewBundle(cfg, bccsp)
Defensive patterns

Strategy: validation

Validate before calling

func validChannelConfig(cfg *cb.Config) bool {
    return cfg != nil && cfg.ChannelGroup != nil
}
if !validChannelConfig(cfg) {
    return fmt.Errorf("refusing to build bundle: config has no channel group")
}
bundle, err := channelconfig.NewBundle(cfg, bccsp)

Type guard

if cg, ok := cfg.ChannelGroup.(*cb.ConfigGroup); ok && cg != nil { /* safe to use cg */ }

Try / catch

bundle, err := channelconfig.NewBundle(cfg, bccsp)
if err != nil && strings.Contains(err.Error(), "config must contain a channel group") {
    // regenerate config / fix construction and retry once
}

Prevention

When it happens

Trigger: Calling NewBundle with a *cb.Config whose ChannelGroup field is nil (or passing a config built without a channel group). preValidate is invoked by NewBundle and anonymous bundle-construction paths, so any bundle creation from a truncated or partially decoded ConfigEnvelope hits it.

Common situations: Hand-crafted or tool-generated config update payloads that only populate an Application or Orderer group at the top level; configtx.yaml output post-processed incorrectly; a marshaled ConfigEnvelope truncated so ChannelGroup fails to unmarshal; tests constructing cb.Config{} directly without ChannelGroup.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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