hyperledger/fabric · error

attempted to change ConsensusType.Type from %s to %s, but Co

Error message

attempted to change ConsensusType.Type from %s to %s, but ConsensusType.State is changing from %s to %s

What it means

inspect rejects a config update that changes both ConsensusType.Type and ConsensusType.State at once. Maintenance-mode transitions require the state change to be accompanied only by the ConsensusType value change (checked by ensureConsensusTypeChangeOnly) — changing the type in the same update as the state is forbidden, so entry/exit from maintenance and the type swap must be separate config updates.

Source

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

	if !ordererConfig.Capabilities().ConsensusTypeMigration() {
		if nextState := nextOrdererConfig.ConsensusState(); nextState != orderer.ConsensusType_STATE_NORMAL {
			return errors.Errorf("next config attempted to change ConsensusType.State to %s, but capability is disabled", nextState)
		}
		if ordererConfig.ConsensusType() != nextOrdererConfig.ConsensusType() {
			return errors.Errorf("next config attempted to change ConsensusType.Type from %s to %s, but capability is disabled",
				ordererConfig.ConsensusType(), nextOrdererConfig.ConsensusType())
		}
		return nil
	}

	// Entry to- and exit from- maintenance-mode should not be accompanied by any other change.
	if ordererConfig.ConsensusState() != nextOrdererConfig.ConsensusState() {
		if err1Change := mf.ensureConsensusTypeChangeOnly(configEnvelope); err1Change != nil {
			return err1Change
		}
		if ordererConfig.ConsensusType() != nextOrdererConfig.ConsensusType() {
			return errors.Errorf("attempted to change ConsensusType.Type from %s to %s, but ConsensusType.State is changing from %s to %s",
				ordererConfig.ConsensusType(), nextOrdererConfig.ConsensusType(), ordererConfig.ConsensusState(), nextOrdererConfig.ConsensusState())
		}
		if !bytes.Equal(nextOrdererConfig.ConsensusMetadata(), ordererConfig.ConsensusMetadata()) {
			return errors.Errorf("attempted to change ConsensusType.Metadata, but ConsensusType.State is changing from %s to %s",
				ordererConfig.ConsensusState(), nextOrdererConfig.ConsensusState())
		}
	}

	// ConsensusType.Type can only change in maintenance-mode, and only within the set of permitted types.
	// Note: only etcdraft to BFT transitions are supported.
	if ordererConfig.ConsensusType() != nextOrdererConfig.ConsensusType() {
		if ordererConfig.ConsensusState() == orderer.ConsensusType_STATE_NORMAL {
			return errors.Errorf("attempted to change consensus type from %s to %s, but current config ConsensusType.State is not in maintenance mode",
				ordererConfig.ConsensusType(), nextOrdererConfig.ConsensusType())
		}
		if nextOrdererConfig.ConsensusState() == orderer.ConsensusType_STATE_NORMAL {
			return errors.Errorf("attempted to change consensus type from %s to %s, but next config ConsensusType.State is not in maintenance mode",
				ordererConfig.ConsensusType(), nextOrdererConfig.ConsensusType())

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Split into sequential updates: (1) enter STATE_MAINTENANCE with type unchanged, (2) change ConsensusType.Type while staying in maintenance, (3) exit to STATE_NORMAL
  2. When entering/exiting maintenance, ensure the type field in the update equals the current type
  3. Generate each step's update by diffing configtxlator output of consecutive states

Example fix

// before: one update changing both
"state": "STATE_MAINTENANCE", "type": "BFT"  // from etcdraft/NORMAL
// after: two updates
// step 1: {"state": "STATE_MAINTENANCE", "type": "etcdraft"}
// step 2: {"state": "STATE_MAINTENANCE", "type": "BFT"}
Defensive patterns

Strategy: validation

Validate before calling

stateChanging := cur.ConsensusState() != next.ConsensusState()
typeChanging := cur.ConsensusType() != next.ConsensusType()
if stateChanging && typeChanging {
	return errors.New("split into separate updates: state transition and type change cannot be combined")
}

Prevention

When it happens

Trigger: A single config update whose Orderer-group write set changes both ConsensusType.Type and ConsensusType.State (e.g. etcdraft/NORMAL to BFT/MAINTENANCE in one shot).

Common situations: Operator tries to shortcut the raft-to-BFT migration by combining steps; scripted update generated from an incorrect diff of current vs final config.

Related errors


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