{"record":{"id":"ddc70a54e68892e2","repo":"hyperledger/fabric","slug":"block-header-is-nil","errorCode":null,"errorMessage":"Block header is nil","messagePattern":"Block header is nil","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gossip/privdata/coordinator.go","lineNumber":158,"sourceCode":"\t\tmspID:                          mspID,\n\t\tstore:                          store,\n\t\tselfSignedData:                 selfSignedData,\n\t\ttransientBlockRetention:        config.TransientBlockRetention,\n\t\tlogger:                         logger.With(\"channel\", support.ChainID),\n\t\tmetrics:                        metrics,\n\t\tpullRetryThreshold:             config.PullRetryThreshold,\n\t\tskipPullingInvalidTransactions: config.SkipPullingInvalidTransactions,\n\t\tidDeserializerFactory:          idDeserializerFactory,\n\t}\n}\n\n// StoreBlock stores block with private data into the ledger\nfunc (c *coordinator) StoreBlock(block *common.Block, privateDataSets util.PvtDataCollections) error {\n\tif block.Data == nil {\n\t\treturn errors.New(\"Block data is empty\")\n\t}\n\tif block.Header == nil {\n\t\treturn errors.New(\"Block header is nil\")\n\t}\n\n\tc.logger.Infof(\"Received block [%d] from buffer\", block.Header.Number)\n\n\tc.logger.Debugf(\"Validating block [%d]\", block.Header.Number)\n\n\tvalidationStart := time.Now()\n\terr := c.Validator.Validate(block)\n\tc.reportValidationDuration(time.Since(validationStart))\n\tif err != nil {\n\t\tc.logger.Errorf(\"Validation failed: %+v\", err)\n\t\treturn err\n\t}\n\n\tblockAndPvtData := &ledger.BlockAndPvtData{\n\t\tBlock:          block,\n\t\tPvtData:        make(ledger.TxPvtDataMap),\n\t\tMissingPvtData: make(ledger.TxMissingPvtData),","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/gossip/privdata/coordinator.go#L140-L176","documentation":"coordinator.StoreBlock requires block.Header to be non-nil because it logs and commits using block.Header.Number. When the header is missing the block cannot be sequenced or validated, so StoreBlock returns this error before any processing.","triggerScenarios":"Calling StoreBlock with a common.Block that has Data set but Header nil — typically from a malformed/incomplete deserialization or hand-built block.","commonSituations":"See trigger scenarios.","solutions":["Re-fetch the block from the orderer/peer to obtain the full block with header","Check that the block deserialization path (protoutil.UnmarshalBlock / FromBlock) preserved the header","Fix test or repair code to include a valid Header with BlockNumber","Inspect the upstream block producer if headers are systematically missing"],"exampleFix":"// before\nblk, _ := protoutil.UnmarshalBlock(bytes) // partial\nc.StoreBlock(blk, pvt)\n// after\nif blk.Header == nil || blk.Data == nil {\n    return fmt.Errorf(\"incomplete block %d\", blk.GetHeader().GetNumber())\n}\nc.StoreBlock(blk, pvt)","handlingStrategy":"type-guard","validationCode":"if block == nil || block.Header == nil || block.Data == nil {\n    return errors.New(\"incomplete block\")\n}","typeGuard":"func hasHeader(b *common.Block) bool {\n    return b != nil && b.Header != nil\n}","tryCatchPattern":null,"preventionTips":["Use protoutil.UnmarshalBlock and check it returned the full block","Never build common.Block by hand without Header in tests","Re-fetch blocks whose header failed to deserialize","Log raw bytes of blocks that arrive headerless to trace corruption"],"tags":["gossip","privdata","ledger","validation"],"backgroundTag":"malformed-block","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"}