{"record":{"id":"abef6f073a02a05a","repo":"hyperledger/fabric","slug":"invalid-block-on-channel-s-block-is-nil","errorCode":null,"errorMessage":"Invalid Block on channel [%s]. Block is nil.","messagePattern":"Invalid Block on channel \\[(.+?)\\]\\. Block is nil\\.","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/peer/gossip/mcs.go","lineNumber":200,"sourceCode":"\tvar consenters []*pcommon.Consenter\n\tif bftEnabled {\n\t\tcfg, ok := chConfig.OrdererConfig()\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"no orderer section in channel config for channel [%s].\", channelID)\n\t\t}\n\t\tconsenters = cfg.Consenters()\n\t}\n\n\tverifier := protoutil.BlockSignatureVerifier(bftEnabled, consenters, policy)\n\treturn verifier(block.Header, block.Metadata)\n}\n\n// VerifyBlockAttestation returns nil when the header matches the metadata signature. It assumed the block.Data is nil\n// and therefore does not verify that Header.DataHash is equal to the hash of block.Data. This is used when the orderer\n// delivers a block with header & metadata only, as an attestation of block existence.\nfunc (s *MSPMessageCryptoService) VerifyBlockAttestation(chainID string, block *pcommon.Block) error {\n\tif block == nil {\n\t\treturn fmt.Errorf(\"Invalid Block on channel [%s]. Block is nil.\", chainID)\n\t}\n\tif block.Header == nil {\n\t\treturn fmt.Errorf(\"Invalid Block on channel [%s]. Header must be different from nil.\", chainID)\n\t}\n\n\t// - Unmarshal medatada\n\tif block.Metadata == nil || len(block.Metadata.Metadata) == 0 {\n\t\treturn fmt.Errorf(\"Block with id [%d] on channel [%s] does not have metadata. Block not valid.\", block.Header.Number, chainID)\n\t}\n\n\treturn s.verifyHeaderAndMetadata(chainID, block)\n}\n\n// Sign signs msg with this peer's signing key and outputs\n// the signature if no error occurred.\nfunc (s *MSPMessageCryptoService) Sign(msg []byte) ([]byte, error) {\n\treturn s.localSigner.Sign(msg)\n}","sourceCodeStart":182,"sourceCodeEnd":218,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/internal/peer/gossip/mcs.go#L182-L218","documentation":"VerifyBlockAttestation was called with a nil *common.Block. The method validates the block pointer before touching any fields and returns this error immediately. It is a caller-side input error: no attestation can be verified for a nonexistent block.","triggerScenarios":"Any invocation of MSPMessageCryptoService.VerifyBlockAttestation(chainID, block) where the block argument is nil — e.g., a gossip callback or delivery handler passing a block that failed to be assigned/parsed upstream.","commonSituations":"Gossip/delivery code paths that propagate nil blocks after failed unmarshaling; callers skipping nil checks on blocks pulled from queues or channels; test harnesses invoking attestation with uninitialized fixtures.","solutions":["Add a nil check on the block before calling VerifyBlockAttestation.","Trace where the block originates (orderer delivery or gossip) and fix the nil propagation at the source.","If the block came from unmarshaling, check that Unmarshal error was handled before use.","Log the channel and caller stack to find which producer supplied the nil block."],"exampleFix":"// before\ncryptoService.VerifyBlockAttestation(chainID, block)\n// after\nif block == nil {\n    return fmt.Errorf(\"refusing attestation check: nil block on channel %s\", chainID)\n}\ncryptoService.VerifyBlockAttestation(chainID, block)","handlingStrategy":"type-guard","validationCode":"if block == nil {\n    return fmt.Errorf(\"nil block cannot be attested on channel %s\", chainID)\n}","typeGuard":"func isAttestableBlock(b *common.Block) bool {\n    return b != nil && b.Header != nil && b.Metadata != nil && len(b.Metadata.Metadata) > 0\n}","tryCatchPattern":"if err := cryptoService.VerifyBlockAttestation(chainID, block); err != nil {\n    if strings.Contains(err.Error(), \"Block is nil\") {\n        log.Warnf(\"skipping attestation: nil block supplied on %s\", chainID)\n        return errSkip\n    }\n    return err\n}","preventionTips":["Nil-check blocks at every handoff between delivery/gossip callbacks and verification","Handle unmarshal errors before using the resulting block pointer","Log block provenance to trace nil-block producers","Add unit tests covering nil-block paths in gossip handlers"],"tags":["hyperledger-fabric","gossip","msp","nil-pointer","block"],"backgroundTag":"nil-block-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"}