hyperledger/fabric · error

envelope to config update unmarshalling error

Error message

envelope to config update unmarshalling error

What it means

Wraps a failure when ensureConsensusTypeChangeOnly converts the config update envelope (configEnvelope.LastUpdate) into a ConfigUpdateEnvelope via protoutil.EnvelopeToConfigUpdate. The submitted envelope is not a well-formed config update (wrong payload type, corrupt bytes), so the migration filter cannot inspect it.

Source

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

		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
}

// ensureConsensusTypeChangeOnly checks that the only change is the Channel/Orderer group, and within that,
// only to the ConsensusType value.
func (mf *MaintenanceFilter) ensureConsensusTypeChangeOnly(configEnvelope *cb.ConfigEnvelope) error {
	configUpdateEnv, err := protoutil.EnvelopeToConfigUpdate(configEnvelope.LastUpdate)
	if err != nil {
		return errors.Wrap(err, "envelope to config update unmarshalling error")
	}

	configUpdate, err := configtx.UnmarshalConfigUpdate(configUpdateEnv.ConfigUpdate)
	if err != nil {
		return errors.Wrap(err, "config update unmarshalling error")
	}

	if len(configUpdate.WriteSet.Groups) == 0 {
		return errors.New("config update contains no changes")
	}

	if len(configUpdate.WriteSet.Values) > 0 {
		return errors.Errorf("config update contains changes to values in group %s", channelconfig.ChannelGroupKey)
	}

	if len(configUpdate.WriteSet.Groups) > 1 {
		return errors.New("config update contains changes to more than one group")
	}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Rebuild the config update envelope with configtxlator proto_encode of a valid ConfigUpdateEnvelope
  2. Ensure the envelope payload type is cb.HeaderType_CONFIG_UPDATE and the ConfigUpdate bytes serialize correctly
  3. Re-run the compute-update/update pipeline in configtxlator from the two config blocks
Defensive patterns

Strategy: validation

Validate before calling

// Go: verify the envelope payload is a CONFIG_UPDATE before submitting
payload := &cb.Payload{}
if err := proto.Unmarshal(env.Payload, payload); err != nil { return err }
if payload.Header.Type != int32(cb.HeaderType_CONFIG_UPDATE) {
    return errors.New("envelope payload is not a config update")
}

Type guard

func isConfigUpdateEnvelope(env *cb.Envelope) bool {
    p := &cb.Payload{}
    return proto.Unmarshal(env.Payload, p) == nil && p.Header.GetType() == int32(cb.HeaderType_CONFIG_UPDATE)
}

Prevention

When it happens

Trigger: Submitting a transaction envelope to the orderer during migration whose payload is not a CONFIG_UPDATE (e.g. a normal data transaction, or a truncated/incorrectly serialized envelope) while it is expected to be the migration update.

Common situations: Using configtxlator or the SDK incorrectly and producing an envelope whose inner payload is mis-typed, or sending the config update envelope before it was fully assembled/signed.

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