hyperledger/fabric · error

config update contains changes to values in group %s

Error message

config update contains changes to values in group %s

What it means

Returned when the config update's WriteSet contains changes to values directly in the top-level Channel group (channelconfig.ChannelGroupKey). The maintenance filter only permits changes inside the Orderer group's ConsensusType value, so any value-level change at the Channel group is rejected.

Source

Thrown at orderer/common/msgprocessor/maintenancefilter.go:184

// ensureConsensusTypeChangeOnly checks that the only change is the Channel/Orderer group, and within that,
// only to the ConsensusType value.
func (mf *MaintenanceFilter) ensureConsensusTypeChangeOnly(configEnvelope *cb.ConfigEnvelope) error {
	configUpdateEnv, err := protoutil.EnvelopeToConfigUpdate(configEnvelope.LastUpdate)
	if err != nil {
		return errors.Wrap(err, "envelope to config update unmarshalling error")
	}

	configUpdate, err := configtx.UnmarshalConfigUpdate(configUpdateEnv.ConfigUpdate)
	if err != nil {
		return errors.Wrap(err, "config update unmarshalling error")
	}

	if len(configUpdate.WriteSet.Groups) == 0 {
		return errors.New("config update contains no changes")
	}

	if len(configUpdate.WriteSet.Values) > 0 {
		return errors.Errorf("config update contains changes to values in group %s", channelconfig.ChannelGroupKey)
	}

	if len(configUpdate.WriteSet.Groups) > 1 {
		return errors.New("config update contains changes to more than one group")
	}

	if ordGroup, ok1 := configUpdate.WriteSet.Groups[channelconfig.OrdererGroupKey]; ok1 {
		if len(ordGroup.Groups) > 0 {
			return errors.Errorf("config update contains changes to groups within the %s group",
				channelconfig.OrdererGroupKey)
		}

		if _, ok2 := ordGroup.Values[channelconfig.ConsensusTypeKey]; !ok2 {
			return errors.Errorf("config update does not contain the %s value", channelconfig.ConsensusTypeKey)
		}

		if len(ordGroup.Values) > 1 {
			return errors.Errorf("config update contain more then just the %s value in the %s group",

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Remove all top-level Channel-group value changes from the update; keep only the Orderer group ConsensusType change
  2. Submit separate config updates: do non-migration value changes before entering maintenance mode or after the migration completes
  3. Recompute the delta so the write set contains only Groups[orderer].Values[ConsensusType]

Example fix

// before: bundled changes
WriteSet: { Values: { Capabilities: ... }, Groups: { Orderer: { Values: { ConsensusType: ... } } } }
// after: only the consensus type change
WriteSet: { Values: {}, Groups: { Orderer: { Values: { ConsensusType: { State: STATE_MAINTENANCE, Type: "BFT" } } } } }
Defensive patterns

Strategy: validation

Validate before calling

if len(update.WriteSet.Values) > 0 {
    return errors.New("update must not change Channel-group values during consensus migration")
}

Prevention

When it happens

Trigger: A maintenance-mode config update whose WriteSet.Values is non-empty, e.g. bundling a change to a Channel-group config value (like BlockValidation or capabilities) together with the consensus type change.

Common situations: Administrators trying to batch multiple config changes (capabilities upgrade plus consensus migration) into a single update while the channel is in maintenance mode.

Related errors


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