{"record":{"id":"41acb263dc3961b5","repo":"hyperledger/fabric","slug":"nil-block-41acb2","errorCode":null,"errorMessage":"nil block","messagePattern":"nil block","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"orderer/consensus/etcdraft/util.go","lineNumber":153,"sourceCode":"func ConfigChannelHeader(block *common.Block) (hdr *common.ChannelHeader, err error) {\n\tenvelope, err := protoutil.ExtractEnvelope(block, 0)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"failed to extract envelope from the block\")\n\t}\n\n\tchannelHeader, err := protoutil.ChannelHeader(envelope)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"cannot extract channel header\")\n\t}\n\n\treturn channelHeader, nil\n}\n\n// ConfigEnvelopeFromBlock extracts configuration envelope from the block based on the\n// config type, i.e. HeaderType_ORDERER_TRANSACTION or HeaderType_CONFIG\nfunc ConfigEnvelopeFromBlock(block *common.Block) (*common.Envelope, error) {\n\tif block == nil {\n\t\treturn nil, errors.New(\"nil block\")\n\t}\n\n\tenvelope, err := protoutil.ExtractEnvelope(block, 0)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"failed to extract envelope from the block\")\n\t}\n\n\tchannelHeader, err := protoutil.ChannelHeader(envelope)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"cannot extract channel header\")\n\t}\n\n\tswitch channelHeader.GetType() {\n\tcase int32(common.HeaderType_ORDERER_TRANSACTION):\n\t\treturn nil, errors.Errorf(\"unsupported legacy system channel header type: %v\", channelHeader.GetType())\n\tcase int32(common.HeaderType_CONFIG):\n\t\treturn envelope, nil\n\tdefault:","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/consensus/etcdraft/util.go#L135-L171","documentation":"ConfigEnvelopeFromBlock returns this error when called with a nil *common.Block. It is a defensive guard: no envelope can be extracted from a nonexistent block, so the function fails fast with a plain sentinel error.","triggerScenarios":"Passing a nil block into ConfigEnvelopeFromBlock, usually indirectly via ConsensusMetadataFromConfigBlock when the caller obtained a nil block (e.g. a failed GetBlockById/RetrieveBlock returned nil without an error).","commonSituations":"Ledger/block retrieval returning (nil, nil); chain puller logic handing through a missing block; ordering system channel removal flows reading a block that was never written.","solutions":["Check for nil before calling: only invoke ConsensusMetadataFromConfigBlock / ConfigEnvelopeFromBlock with a block confirmed non-nil.","Fix the upstream block-retrieval path so a missing block is surfaced as an error instead of (nil, nil).","In tests, ensure block fixtures are actually assigned before use."],"exampleFix":"// before\nblock, _ := ledger.GetBlockByNumber(5) // may be nil\nmeta, _, err := ConsensusMetadataFromConfigBlock(block)\n\n// after\nblock, err := ledger.GetBlockByNumber(5)\nif err != nil {\n    return err\n}\nif block == nil {\n    return errors.New(\"block 5 not found in ledger\")\n}\nmeta, _, err := ConsensusMetadataFromConfigBlock(block)","handlingStrategy":"type-guard","validationCode":"if block == nil {\n    return errors.New(\"config block is nil\")\n}","typeGuard":"func nonNilBlock(block *common.Block) bool {\n    return block != nil && block.Header != nil && block.Data != nil\n}","tryCatchPattern":"envelope, err := ConfigEnvelopeFromBlock(block)\nif err != nil {\n    if err.Error() == \"nil block\" {\n        return errors.New(\"block retrieval returned nothing\")\n    }\n    return err\n}","preventionTips":["Never ignore the error return of block-lookup APIs (avoid `block, _ :=`).","Treat a nil block result from the ledger as an explicit 'not found' error.","Initialize test fixtures before use; assert non-nil in test setup."],"tags":["hyperledger-fabric","etcdraft","nil-pointer","block-parsing"],"backgroundTag":"nil-input-argument","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"}