hyperledger/fabric · error

invalid options encoded in consensus metadata: %v

Error message

invalid options encoded in consensus metadata: %v

What it means

The ConsensusType value unmarshaled fine, but its Metadata must itself unmarshal into a smartbft.Options protobuf. A malformed Metadata blob means the BFT options (ticks, timeouts, leader rotation, etc.) cannot be read, so the update is rejected.

Source

Thrown at orderer/consensus/smartbft/configverifier.go:182

	if !proto.Equal(expectedConfigPol, actualPolicy) {
		return fmt.Errorf("block validation policy should be a signature policy: %v but it is %v instead", expectedConfigPol, actualPolicy)
	}

	consensusTypeConfigValue := conf.ChannelGroup.Groups["Orderer"].Values["ConsensusType"]

	if consensusTypeConfigValue == nil {
		return fmt.Errorf("missing consensus type property in config")
	}

	consensusTypeValue := &protosorderer.ConsensusType{}
	if err := proto.Unmarshal(consensusTypeConfigValue.Value, consensusTypeValue); err != nil {
		return fmt.Errorf("invalid consensus type property in config: %v", err)
	}

	configOptions := &smartbft.Options{}
	if err := proto.Unmarshal(consensusTypeValue.Metadata, configOptions); err != nil {
		return fmt.Errorf("invalid options encoded in consensus metadata: %v", err)
	}

	if configOptions.LeaderRotation == smartbft.Options_ROTATION_ON {
		return fmt.Errorf("leader rotation must be turned off for this version or be unspecified")
	}

	return nil
}

func (cbv *ConfigBlockValidator) verifyConfigUpdateMsg(outEnv *common.Envelope, confEnv *common.ConfigEnvelope, chdr *common.ChannelHeader) error {
	if confEnv == nil || confEnv.LastUpdate == nil || confEnv.Config == nil {
		return errors.New("invalid config envelope")
	}
	envPayload, err := protoutil.UnmarshalPayload(confEnv.LastUpdate.Payload)
	if err != nil {
		return err
	}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Marshal Metadata from a correct &smartbft.Options{} message and store it in ConsensusType.Metadata
  2. Use configtxgen / the SmartBFT sample config to produce consensusMetadata instead of hand-writing bytes
  3. Decode the raw metadata with protoc --decode_raw to diagnose the wrong content

Example fix

// before
metadata, _ := proto.Marshal(&etcdraft.Metadata{Consenters: consenters}) // wrong proto type for BFT
// after
metadata, _ := proto.Marshal(&smartbft.Options{DecisionTimeout: 500, LeaderRotation: smartbft.Options_ROTATION_OFF})
Defensive patterns

Strategy: validation

Validate before calling

opts := &smartbft.Options{}
if err := proto.Unmarshal(consensusTypeValue.Metadata, opts); err != nil {
    return fmt.Errorf("consensus metadata is not valid smartbft.Options: %w", err)
}

Try / catch

if err := verifyMetadata(consensusTypeValue.Metadata); err != nil {
    return fmt.Errorf("aborting config submission: %w", err)
}

Prevention

When it happens

Trigger: proto.Unmarshal(consensusTypeValue.Metadata, configOptions) fails in checkConsentersMatchPolicy — Metadata bytes are empty-but-non-nil garbage, wrong message type, or corrupted.

Common situations: Consenter metadata assembled by custom tooling using the wrong proto; hand-edited consensus metadata; ordering-node versions writing incompatible Options fields; copying metadata from an etcdraft channel into a BFT channel.

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/e01d4b54341da394. Report an issue: GitHub.