hyperledger/fabric · error

invalid BFT metadata configuration

Error message

invalid BFT metadata configuration

What it means

Returned when the BFT metadata unmarshals as smartbft.Options but util.ConfigFromMetadataOptions fails to derive a valid consensus configuration from it. The metadata is structurally a valid protobuf but semantically invalid (e.g. bad batch settings, invalid timeouts, or empty leader-related options).

Source

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

		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",
				ordererConfig.ConsensusType(), nextOrdererConfig.ConsensusType())
		}

		if nextOrdererConfig.ConsensusType() == "BFT" {
			updatedMetadata := &smartbft.Options{}
			if err := proto.Unmarshal(nextOrdererConfig.ConsensusMetadata(), updatedMetadata); err != nil {
				return errors.Wrap(err, "failed to unmarshal BFT metadata configuration")
			}

			_, err := util.ConfigFromMetadataOptions(1, updatedMetadata)
			if err != nil {
				return errors.New("invalid BFT metadata configuration")
			}

			err = validateBFTConsenterMapping(ordererConfig, nextOrdererConfig)
			if err != nil {
				return errors.Wrap(err, "invalid BFT consenter mapping configuration")
			}
		}

		logger.Infof("[channel: %s] consensus-type migration: about to change from %s to %s",
			mf.support.ChannelID(), ordererConfig.ConsensusType(), nextOrdererConfig.ConsensusType())
	}

	if nextOrdererConfig.ConsensusState() != ordererConfig.ConsensusState() {
		logger.Infof("[channel: %s] maintenance mode: ConsensusType.State about to change from %s to %s",
			mf.support.ChannelID(), ordererConfig.ConsensusState(), nextOrdererConfig.ConsensusState())
	}

	return nil

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Fix the smartbft.Options values so ConfigFromMetadataOptions can build a valid config (positive batch sizes, valid timeouts)
  2. Start from a known-good BFT metadata generated by configtxgen/configtxlator for your Fabric version
  3. Check orderer local config examples for the version you are migrating to and mirror the option values

Example fix

// before: invalid option
"RequestBatchMaxCount": 0
// after: valid option
"RequestBatchMaxCount": 100
Defensive patterns

Strategy: validation

Validate before calling

opts := &smartbft.Options{}
if err := proto.Unmarshal(metadata, opts); err != nil { return err }
if _, err := util.ConfigFromMetadataOptions(1, opts); err != nil {
    return fmt.Errorf("BFT options semantically invalid: %w", err)
}

Prevention

When it happens

Trigger: A maintenance-mode migration to BFT where the smartbft.Options in ConsensusMetadata contain values that ConfigFromMetadataOptions cannot convert into a valid localconfig consensus config (invalid numeric or duration fields, out-of-range options).

Common situations: Administrators crafting BFT metadata by hand with wrong units for timeouts, zero/negative batch sizes, or options copied from an incompatible Fabric version.

Related errors


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