hyperledger/fabric · error

config transaction inspection failed

Error message

config transaction inspection failed

What it means

MaintenanceFilter.Apply wraps any error returned by mf.inspect() with "config transaction inspection failed". It means the envelope parsed correctly, but the proposed next orderer config violated one of the consensus-type migration (maintenance mode) transition rules. The transaction is rejected and the wrapped inner error names the specific rule broken.

Source

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

// Apply applies the maintenance filter on a CONFIG tx.
func (mf *MaintenanceFilter) Apply(message *cb.Envelope) error {
	ordererConf, ok := mf.support.OrdererConfig()
	if !ok {
		logger.Panic("Programming error: orderer config not found")
	}

	configEnvelope := &cb.ConfigEnvelope{}
	chanHdr, err := protoutil.UnmarshalEnvelopeOfType(message, cb.HeaderType_CONFIG, configEnvelope)
	if err != nil {
		return errors.Wrap(err, "envelope unmarshalling failed")
	}

	logger.Debugw("Going to inspect maintenance mode transition rules",
		"ConsensusState", ordererConf.ConsensusState(), "channel", chanHdr.ChannelId)
	err = mf.inspect(configEnvelope, ordererConf)
	if err != nil {
		return errors.Wrap(err, "config transaction inspection failed")
	}

	return nil
}

// inspect checks whether the next orderer config, extracted from the incoming configEnvelope, respects the
// transition rules of consensus-type migration using maintenance-mode.
func (mf *MaintenanceFilter) inspect(configEnvelope *cb.ConfigEnvelope, ordererConfig channelconfig.Orderer) error {
	if configEnvelope.LastUpdate == nil {
		return errors.Errorf("updated config does not include a config update")
	}

	bundle, err := channelconfig.NewBundle(mf.support.ChannelID(), configEnvelope.Config, mf.bccsp)
	if err != nil {
		return errors.Wrap(err, "failed to parse config")
	}

	nextOrdererConfig, ok := bundle.OrdererConfig()

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Read the wrapped inner error (errors.Cause) to identify the exact violated rule
  2. Follow the correct migration sequence: enable V2_0/V3 capabilities, enter STATE_MAINTENANCE, change type, exit to STATE_NORMAL, in separate config updates
  3. Ensure only the ConsensusType value in the Orderer group changes when transitioning state (see ensureConsensusTypeChangeOnly)
  4. Enable ConsensusTypeMigration in the channel capabilities if migration is intended
Defensive patterns

Strategy: validation

Validate before calling

oc, ok := support.OrdererConfig()
if !ok { panic("no orderer config") }
if !oc.Capabilities().ConsensusTypeMigration() { return errors.New("migration capability not enabled") }
if oc.ConsensusState() != orderer.ConsensusType_STATE_MAINTENANCE && changingType { return errors.New("not in maintenance mode") }

Try / catch

if err := filter.Apply(env); err != nil {
	if strings.Contains(err.Error(), "config transaction inspection failed") {
		cause := errors.Cause(err)
		log.Errorf("migration rule violated: %v", cause)
		return err
	}
}

Prevention

When it happens

Trigger: Submitting a channel config update that touches orderer.ConsensusType or ConsensusState while it violates migration rules: LastUpdate nil, unparsable config, missing orderer group, capability disabled, changing type/metadata along with state, type change outside maintenance mode, or unsupported target type.

Common situations: Operators following outdated etcdraft-to-BFT migration docs; changing consensus type without first entering STATE_MAINTENANCE; bundling other config changes in the same update as a state transition; ConsensusTypeMigration capability not enabled in the channel.

Related errors


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