{"record":{"id":"952df06436045947","repo":"hyperledger/fabric","slug":"block-must-be-different-from-nil-channel-s","errorCode":null,"errorMessage":"block must be different from nil, channel=%s","messagePattern":"block must be different from nil, channel=(.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/deliverclient/block_verification.go","lineNumber":313,"sourceCode":"\n// UpdateBlockHeader saves the last block header that was verified and handled successfully.\n// This must be called after VerifyBlock and VerifyBlockAttestation and successfully handling the block.\nfunc (a *BlockVerificationAssistant) UpdateBlockHeader(block *common.Block) {\n\ta.lastBlockHeader = block.Header\n\ta.lastBlockHeaderHash = protoutil.BlockHeaderHash(block.Header)\n}\n\nfunc (a *BlockVerificationAssistant) verifyMetadata(block *common.Block) error {\n\tif block.Metadata == nil || len(block.Metadata.Metadata) < len(common.BlockMetadataIndex_name) {\n\t\treturn errors.Errorf(\"block with id [%d] on channel [%s] does not have metadata or contains too few entries\", block.Header.Number, a.channelID)\n\t}\n\n\treturn nil\n}\n\nfunc (a *BlockVerificationAssistant) verifyHeader(block *common.Block) error {\n\tif block == nil {\n\t\treturn errors.Errorf(\"block must be different from nil, channel=%s\", a.channelID)\n\t}\n\tif block.Header == nil {\n\t\treturn errors.Errorf(\"invalid block, header must be different from nil, channel=%s\", a.channelID)\n\t}\n\n\texpectedBlockNum := a.lastBlockHeader.Number + 1\n\tif expectedBlockNum != block.Header.Number {\n\t\treturn errors.Errorf(\"expected block number is [%d] but actual block number inside block is [%d]\", expectedBlockNum, block.Header.Number)\n\t}\n\n\tif len(a.lastBlockHeaderHash) != 0 {\n\t\tif !bytes.Equal(block.Header.PreviousHash, a.lastBlockHeaderHash) {\n\t\t\treturn errors.Errorf(\"Header.PreviousHash of block [%d] is different from Hash(block.Header) of previous block, on channel [%s], received: %s, expected: %s\",\n\t\t\t\tblock.Header.Number, a.channelID, hex.EncodeToString(block.Header.PreviousHash), hex.EncodeToString(a.lastBlockHeaderHash))\n\t\t}\n\t}\n\treturn nil\n}","sourceCodeStart":295,"sourceCodeEnd":331,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/common/deliverclient/block_verification.go#L295-L331","documentation":"verifyHeader is the first check in block chain verification: a nil block cannot be verified against the expected sequence number (lastBlockHeader.Number + 1), so it is rejected immediately with the channel name in the message.","triggerScenarios":"VerifyBlock or VerifyBlockAttestation invoked with a nil *common.Block — typically a deliver client callback received a nil block (failed unmarshalling of the delivered message, or a placeholder nil passed in custom code).","commonSituations":"Custom deliver handlers passing the block variable without checking it after a failed/unsuccessful delivery; mocks in tests returning nil; a nil result from a decode helper silently propagated.","solutions":["Guard the caller: check block != nil (and block.Header != nil) before calling VerifyBlock/VerifyBlockAttestation.","Check why the deliver stream produced a nil block — inspect the received DeliverResponse/Envelope unmarshalling errors.","Log the delivery response error instead of discarding it before invoking verification."],"exampleFix":"// before\nif err := bva.VerifyBlock(recvBlock, cryptoOpts); err != nil {...}\n\n// after\nif recvBlock == nil || recvBlock.Header == nil {\n    return fmt.Errorf(\"no block received from orderer\")\n}\nif err := bva.VerifyBlock(recvBlock, cryptoOpts); err != nil {...}","handlingStrategy":"type-guard","validationCode":"if block == nil || block.Header == nil {\n    return errors.New(\"deliver response contained no block\")\n}","typeGuard":"func isVerifiableBlock(block *common.Block) bool {\n    return block != nil && block.Header != nil\n}","tryCatchPattern":"resp, err := deliverStream.Recv()\nif err != nil { return err }\nblock, err := protoutil.UnmarshalBlock(resp.GetBlock())\nif err != nil || block == nil { return fmt.Errorf(\"failed to decode delivered block: %w\", err) }\nreturn bva.VerifyBlock(block, opts)","preventionTips":["Always check deliver stream errors before using the returned block","Unmarshal delivered envelopes with protoutil.UnmarshalBlock and propagate its error","Never pass through nil from mocks/helpers without explicit failure handling"],"tags":["hyperledger-fabric","deliver-client","nil-check"],"backgroundTag":"nil-block-input","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"}