hyperledger/fabric · error

no 'Orderer' group in channel groups

Error message

no 'Orderer' group in channel groups

What it means

The SmartBFT consenter checks live under ChannelGroup.Groups["Orderer"]. If that group is absent the verifier cannot read the 'Orderers' value or the BlockValidation policy, so it fails with 'no Orderer group in channel groups'. This is SmartBFT-specific: a BFT channel must have an Orderer group defining its consenter mapping.

Source

Thrown at orderer/consensus/smartbft/configverifier.go:108

		return errors.Errorf("unexpected envelope type %s", common.HeaderType_name[chdr.Type])
	}
}

func (cbv *ConfigBlockValidator) checkConsentersMatchPolicy(conf *common.Config) error {
	if conf == nil {
		return fmt.Errorf("empty Config")
	}

	if conf.ChannelGroup == nil {
		return fmt.Errorf("empty channel group")
	}

	if len(conf.ChannelGroup.Groups) == 0 {
		return fmt.Errorf("no groups in channel group")
	}

	if conf.ChannelGroup.Groups["Orderer"] == nil {
		return fmt.Errorf("no 'Orderer' group in channel groups")
	}

	if len(conf.ChannelGroup.Groups["Orderer"].Values) == 0 {
		return fmt.Errorf("no values in 'Orderer' group")
	}

	if conf.ChannelGroup.Groups["Orderer"].Values["Orderers"] == nil {
		return fmt.Errorf("no values in 'Orderer' group")
	}

	ords := &common.Orderers{}
	if err := proto.Unmarshal(conf.ChannelGroup.Groups["Orderer"].Values["Orderers"].Value, ords); err != nil {
		return err
	}

	n := len(ords.ConsenterMapping)
	f := (n - 1) / 3

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Ensure ChannelGroup.Groups contains an "Orderer" group populated by the orderer section of your configtx profile
  2. Regenerate the channel config with configtxgen using a profile with Orderer: Orderers/ConsensusType set for SmartBFT
  3. If converting an existing channel, perform the standard consensus-type migration steps so the Orderer group and 'Orderers' value exist

Example fix

// before
Groups: map[string]*common.ConfigGroup{"Application": appGroup} // missing Orderer
// after
Groups: map[string]*common.ConfigGroup{
  "Orderer": ordererGroup, // contains Values["Orderers"], Values["ConsensusType"], Policies["BlockValidation"]
  "Application": appGroup,
}
Defensive patterns

Strategy: validation

Validate before calling

func hasOrdererGroup(conf *common.Config) bool {
  return conf != nil && conf.ChannelGroup != nil && conf.ChannelGroup.Groups["Orderer"] != nil
}

Type guard

func hasOrdererGroup(c *common.Config) bool {
  return c != nil && c.GetChannelGroup() != nil && c.GetChannelGroup().GetGroups()["Orderer"] != nil
}

Try / catch

if err := cbv.ValidateConfig(envelope); err != nil {
  if strings.Contains(err.Error(), "no 'Orderer' group") {
    return fmt.Errorf("not a valid SmartBFT channel config: %w", err)
  }
  return err
}

Prevention

When it happens

Trigger: Validating a SmartBFT channel config whose ChannelGroup.Groups lacks an "Orderer" key — e.g. an application-only config, a config produced for a Raft/Solo channel, or a typo'd group name in generated config.

Common situations: Switching a channel to SmartBFT without regenerating the full orderer config; configtx profiles omitting the Orderer section; tooling that builds the config tree with only Application groups.

Related errors


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