hyperledger/fabric · error

failed to unmarshal BFT metadata configuration

Error message

failed to unmarshal BFT metadata configuration

What it means

Wraps a protobuf unmarshal failure when the maintenance filter tries to parse the next config's ConsensusMetadata as smartbft.Options during a migration to the BFT consensus type. If the metadata bytes are not a valid protobuf smartbft.Options message, the update is rejected with this wrapped error.

Source

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

	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",
				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() {

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Regenerate the BFT ConsensusMetadata as a valid protobuf-encoded smartbft.Options message and base64 it in the config update
  2. Use configtxlator to decode, edit, and re-encode the config instead of hand-crafting bytes
  3. Verify the metadata decodes with protoc --decode=smartbft.Options against the fabric-protos definitions
Defensive patterns

Strategy: validation

Validate before calling

// Go: verify metadata round-trips as smartbft.Options before submitting
opts := &smartbft.Options{}
if err := proto.Unmarshal(metadata, opts); err != nil {
    return fmt.Errorf("BFT metadata invalid: %w", err)
}

Try / catch

if err := applyUpdate(env); err != nil {
    if strings.Contains(err.Error(), "failed to unmarshal BFT metadata configuration") {
        // regenerate metadata with configtxlator and resubmit
    }
}

Prevention

When it happens

Trigger: A maintenance-mode config update changing consensus type to "BFT" whose ConsensusMetadata field is missing, truncated, or not a valid proto-encoded smartbft.Options message.

Common situations: Hand-editing the config JSON with configtxlator and corrupting the metadata (wrong base64, wrong schema, plain JSON pasted where protobuf bytes are expected), or copying metadata from a non-BFT consensus type without regenerating it.

Understand the failure class

Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.

Related errors


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