hyperledger/fabric · error

failed unmarshalling envelope of config block

Error message

failed unmarshalling envelope of config block

What it means

remoteNodesFromConfigBlock unmarshals block.Data.Data[0] as a cb.Envelope; on failure it returns 'failed unmarshalling envelope of config block' with the underlying protobuf error wrapped. The first entry of a config block's data must be an Envelope containing a ConfigUpdate/Config transaction; if the bytes are corrupt or not an envelope the node cannot extract orderer nodes from the block.

Source

Thrown at orderer/consensus/smartbft/util.go:285

	}

	chdr, err := protoutil.UnmarshalChannelHeader(payload.Header.ChannelHeader)
	if err != nil {
		return nil, errors.WithMessage(err, "error unmarshalling channel header")
	}

	return &request{
		chHdr:    chdr,
		sigHdr:   sigHdr,
		envelope: envelope,
	}, nil
}

// remoteNodesFromConfigBlock unmarshalls the node config from the block metadata
func remoteNodesFromConfigBlock(block *cb.Block, logger *flogging.FabricLogger, bccsp bccsp.BCCSP) (*nodeConfig, error) {
	env := &cb.Envelope{}
	if err := proto.Unmarshal(block.Data.Data[0], env); err != nil {
		return nil, errors.Wrap(err, "failed unmarshalling envelope of config block")
	}
	bundle, err := channelconfig.NewBundleFromEnvelope(env, bccsp)
	if err != nil {
		return nil, errors.Wrap(err, "failed getting a new bundle from envelope of config block")
	}

	channelMSPs, err := bundle.MSPManager().GetMSPs()
	if err != nil {
		return nil, errors.Wrap(err, "failed obtaining MSPs from MSPManager")
	}

	oc, ok := bundle.OrdererConfig()
	if !ok {
		return nil, errors.New("no orderer config in config block")
	}

	_, err = createSmartBftConfig(oc)
	if err != nil {

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Verify the block is a genuine config block: protoutil.IsConfigBlock(block) before processing
  2. Check ledger integrity (file/raft ledger logs, snapshot checksums) and repair or resync from peers/snapshot
  3. Re-fetch the block from a healthy orderer or from the genesis file; restart the orderer after fixing storage
  4. Confirm block.Data is non-empty (len(Data.Data) > 0) before indexing element 0

Example fix

// before
env := &cb.Envelope{}
if err := proto.Unmarshal(block.Data.Data[0], env); err != nil {...}
// after
if !protoutil.IsConfigBlock(block) {
    return nil, errors.New("not a config block")
}
env := &cb.Envelope{}
if err := proto.Unmarshal(block.Data.Data[0], env); err != nil {...}
Defensive patterns

Strategy: validation

Validate before calling

func isUsableConfigBlock(block *cb.Block) bool {
    return block != nil && block.Data != nil && len(block.Data.Data) > 0 && protoutil.IsConfigBlock(block)
}

Type guard

func isBlock(b *cb.Block) bool { return b != nil && b.Header != nil && b.Data != nil && len(b.Data.Data) > 0 }

Try / catch

nodeCfg, err := remoteNodesFromConfigBlock(block, logger, bccsp)
if err != nil {
    if strings.Contains(err.Error(), "failed unmarshalling envelope of config block") {
        logger.Panicf("config block corrupt, resync required: %v", err)
    }
    return err
}

Prevention

When it happens

Trigger: configBlockCommitted receives a committed block whose Data.Data[0] is not a valid protobuf Envelope — corrupt block storage, a non-genesis/foreign block passed in, or a block truncated on disk.

Common situations: Corrupted file ledger / snapshot restore mid-block; passing a regular (non-config) block or nil data into remoteNodesFromConfigBlock in tests; migrating chains between Fabric versions with different block encoding.

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