{"record":{"id":"e5daa2a9b41968c1","repo":"hyperledger/fabric","slug":"failed-unmarshalling-envelope-of-config-block","errorCode":null,"errorMessage":"failed unmarshalling envelope of config block","messagePattern":"failed unmarshalling envelope of config block","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"orderer/consensus/smartbft/util.go","lineNumber":285,"sourceCode":"\t}\n\n\tchdr, err := protoutil.UnmarshalChannelHeader(payload.Header.ChannelHeader)\n\tif err != nil {\n\t\treturn nil, errors.WithMessage(err, \"error unmarshalling channel header\")\n\t}\n\n\treturn &request{\n\t\tchHdr:    chdr,\n\t\tsigHdr:   sigHdr,\n\t\tenvelope: envelope,\n\t}, nil\n}\n\n// remoteNodesFromConfigBlock unmarshalls the node config from the block metadata\nfunc remoteNodesFromConfigBlock(block *cb.Block, logger *flogging.FabricLogger, bccsp bccsp.BCCSP) (*nodeConfig, error) {\n\tenv := &cb.Envelope{}\n\tif err := proto.Unmarshal(block.Data.Data[0], env); err != nil {\n\t\treturn nil, errors.Wrap(err, \"failed unmarshalling envelope of config block\")\n\t}\n\tbundle, err := channelconfig.NewBundleFromEnvelope(env, bccsp)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"failed getting a new bundle from envelope of config block\")\n\t}\n\n\tchannelMSPs, err := bundle.MSPManager().GetMSPs()\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"failed obtaining MSPs from MSPManager\")\n\t}\n\n\toc, ok := bundle.OrdererConfig()\n\tif !ok {\n\t\treturn nil, errors.New(\"no orderer config in config block\")\n\t}\n\n\t_, err = createSmartBftConfig(oc)\n\tif err != nil {","sourceCodeStart":267,"sourceCodeEnd":303,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/consensus/smartbft/util.go#L267-L303","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Verify the block is a genuine config block: protoutil.IsConfigBlock(block) before processing","Check ledger integrity (file/raft ledger logs, snapshot checksums) and repair or resync from peers/snapshot","Re-fetch the block from a healthy orderer or from the genesis file; restart the orderer after fixing storage","Confirm block.Data is non-empty (len(Data.Data) > 0) before indexing element 0"],"exampleFix":"// before\nenv := &cb.Envelope{}\nif err := proto.Unmarshal(block.Data.Data[0], env); err != nil {...}\n// after\nif !protoutil.IsConfigBlock(block) {\n    return nil, errors.New(\"not a config block\")\n}\nenv := &cb.Envelope{}\nif err := proto.Unmarshal(block.Data.Data[0], env); err != nil {...}","handlingStrategy":"validation","validationCode":"func isUsableConfigBlock(block *cb.Block) bool {\n    return block != nil && block.Data != nil && len(block.Data.Data) > 0 && protoutil.IsConfigBlock(block)\n}","typeGuard":"func isBlock(b *cb.Block) bool { return b != nil && b.Header != nil && b.Data != nil && len(b.Data.Data) > 0 }","tryCatchPattern":"nodeCfg, err := remoteNodesFromConfigBlock(block, logger, bccsp)\nif err != nil {\n    if strings.Contains(err.Error(), \"failed unmarshalling envelope of config block\") {\n        logger.Panicf(\"config block corrupt, resync required: %v\", err)\n    }\n    return err\n}","preventionTips":["Check protoutil.IsConfigBlock before processing any block as a config block","Enable ledger checksums and verify snapshot integrity before restore","Keep orderer storage healthy (disk space, clean shutdowns) to avoid truncated blocks"],"tags":["hyperledger-fabric","smartbft","protobuf","unmarshal","config-block","block-corruption"],"backgroundTag":"protobuf-unmarshal-failed","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}