hyperledger/fabric · error

attempted to change ConsensusType.Metadata, but ConsensusTyp

Error message

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

What it means

inspect rejects a config update that changes ConsensusType.Metadata while ConsensusType.State is also changing. Maintenance-mode entry/exit must not be accompanied by any change other than the state itself (after ensureConsensusTypeChangeOnly, metadata must be byte-identical), so metadata (e.g. etcdraft consenters or BFT options) must be updated in a separate config update.

Source

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

		}
		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())
		}

		if !mf.permittedTargetConsensusTypes[nextOrdererConfig.ConsensusType()] {
			return errors.Errorf("attempted to change consensus type from %s to %s, transition not supported",

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Make the state transition its own config update with metadata byte-identical to the current metadata
  2. Perform metadata changes (e.g. BFT options) in a separate update while state is stable (in maintenance)
  3. Copy the existing metadata value verbatim when creating the state-transition update
Defensive patterns

Strategy: validation

Validate before calling

if cur.ConsensusState() != next.ConsensusState() && !bytes.Equal(cur.ConsensusMetadata(), next.ConsensusMetadata()) {
	return errors.New("metadata must be byte-identical during a state transition")
}

Prevention

When it happens

Trigger: A single Orderer-group update that both transitions ConsensusType.State and modifies ConsensusType.Metadata bytes.

Common situations: Editing consenters/TLS certs at the same time as entering maintenance; regenerating metadata (field ordering/whitespace) causing byte inequality despite semantic equality; combining exit-from-maintenance with metadata refresh.

Related errors


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