{"record":{"id":"887988f2076a3d99","repo":"hyperledger/fabric","slug":"last-block-header-hash-is-missing","errorCode":null,"errorMessage":"last block header hash is missing","messagePattern":"last block header hash is missing","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/deliverclient/block_verification.go","lineNumber":161,"sourceCode":"\t\tconfigBlockHeader:   configBlock.Header,\n\t\tlastBlockHeader:     lastBlock.Header,\n\t\tlastBlockHeaderHash: protoutil.BlockHeaderHash(lastBlock.Header),\n\t\tlogger:              lg,\n\t}\n\n\treturn a, nil\n}\n\n// NewBlockVerificationAssistantFromConfig creates a new BlockVerificationAssistant from a common.Config.\n// This is used in the peer, since when the peer starts from a snapshot we may not have access to the last config-block,\n// only to the config object.\nfunc NewBlockVerificationAssistantFromConfig(config *common.Config, lastBlockNumber uint64, lastBlockHeaderHash []byte, channelID string, cryptoProvider bccsp.BCCSP, lg *flogging.FabricLogger) (*BlockVerificationAssistant, error) {\n\tif config == nil {\n\t\treturn nil, errors.Errorf(\"config is nil\")\n\t}\n\n\tif len(lastBlockHeaderHash) == 0 {\n\t\treturn nil, errors.Errorf(\"last block header hash is missing\")\n\t}\n\n\tbva := &BlockVerifierAssembler{\n\t\tLogger: lg,\n\t\tBCCSP:  cryptoProvider,\n\t}\n\tverifierFunc, err := bva.VerifierFromConfig(&common.ConfigEnvelope{Config: config}, channelID)\n\tif err != nil {\n\t\treturn nil, errors.WithMessage(err, \"error creating verifier function\")\n\t}\n\n\ta := &BlockVerificationAssistant{\n\t\tchannelID:           channelID,\n\t\tverifierAssembler:   bva,\n\t\tsigVerifierFunc:     verifierFunc,\n\t\tlastBlockHeader:     &common.BlockHeader{Number: lastBlockNumber},\n\t\tlastBlockHeaderHash: lastBlockHeaderHash,\n\t\tlogger:              lg,","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/common/deliverclient/block_verification.go#L143-L179","documentation":"NewBlockVerificationAssistantFromConfig requires the hash of the last delivered block's header to seed chain verification of subsequent blocks. An empty lastBlockHeaderHash means the assistant could not anchor the next block's PreviousHash check, so construction fails immediately.","triggerScenarios":"Calling NewBlockVerificationAssistantFromConfig (directly or via a deliver client factory) with a nil/empty lastBlockHeaderHash argument — typically when a caller computed the last header hash from a nil/zero last block, or passed an unset variable.","commonSituations":"Custom block-replay/verification tools calling the constructor on a fresh channel without first fetching the genesis block header hash; wiring the deliver client before any block was cached.","solutions":["Fetch the channel's last block (e.g. via OrdererClient SendReceive / query ledger height) and compute lastBlockHeaderHash = protoutil.BlockHeaderHash(lastBlock.Header).","For a fresh ledger, start from the genesis block and pass protoutil.BlockHeaderHash(genesisBlock.Header).","Guard the call site: skip or correct the call when the cached last block is nil."],"exampleFix":"// before\nbva, err := NewBlockVerificationAssistantFromConfig(config, lastNum, nil, chID, bccsp, lg)\n\n// after\nif lastBlock == nil || lastBlock.Header == nil { return errors.New(\"no last block available\") }\nlastHash := protoutil.BlockHeaderHash(lastBlock.Header)\nbva, err := NewBlockVerificationAssistantFromConfig(config, lastNum, lastHash, chID, bccsp, lg)","handlingStrategy":"validation","validationCode":"if len(lastBlockHeaderHash) == 0 {\n    last, err := fetchLastBlock(ordererClient, channelID)\n    if err != nil { return err }\n    lastBlockHeaderHash = protoutil.BlockHeaderHash(last.Header)\n}\nbva, err := NewBlockVerificationAssistantFromConfig(config, lastNum, lastBlockHeaderHash, channelID, bccsp, lg)","typeGuard":"func hasLastHeaderHash(h []byte) bool { return len(h) > 0 }","tryCatchPattern":"bva, err := NewBlockVerificationAssistantFromConfig(cfg, num, hash, chID, bccsp, lg)\nif err != nil {\n    if strings.Contains(err.Error(), \"last block header hash is missing\") {\n        // fetch last block and retry once\n    }\n    return err\n}","preventionTips":["Compute the hash from the actual last block (protoutil.BlockHeaderHash), never pass unset variables","For fresh channels anchor on the genesis block header hash","Keep the last block cached alongside its hash to avoid divergence"],"tags":["hyperledger-fabric","deliver-client","block-verification"],"backgroundTag":"missing-required-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"}