{"record":{"id":"e7582bebc01e70eb","repo":"hyperledger/fabric","slug":"block-header-is-nil-e7582b","errorCode":null,"errorMessage":"block header is nil","messagePattern":"block header is nil","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"orderer/common/follower/follower_chain.go","lineNumber":180,"sourceCode":"\tif ledgerResources.Height() > 0 {\n\t\tif err := chain.loadLastConfig(); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif err := blockPullerFactory.UpdateVerifierFromConfigBlock(chain.lastConfig); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\tif joinBlock == nil {\n\t\tchain.status = types.StatusActive\n\t\tif isMem, _ := chain.clusterConsenter.IsChannelMember(chain.lastConfig); isMem {\n\t\t\tchain.consensusRelation = types.ConsensusRelationConsenter\n\t\t}\n\n\t\tchain.logger.Infof(\"Created with a nil join-block, ledger height: %d\", chain.firstHeight)\n\t} else {\n\t\tif joinBlock.Header == nil {\n\t\t\treturn nil, errors.New(\"block header is nil\")\n\t\t}\n\t\tif joinBlock.Data == nil {\n\t\t\treturn nil, errors.New(\"block data is nil\")\n\t\t}\n\n\t\t// Check the block puller creation function once before we start the follower. This ensures we can extract\n\t\t// the endpoints from the join-block.\n\t\tpuller, err := blockPullerFactory.BlockPuller(joinBlock, nil)\n\t\tif err != nil {\n\t\t\treturn nil, errors.WithMessage(err, \"error creating a block puller from join-block\")\n\t\t}\n\t\tpuller.Close()\n\n\t\tif chain.joinBlock.Header.Number < chain.ledgerResources.Height() {\n\t\t\tchain.status = types.StatusActive\n\t\t}\n\t\tif isMem, _ := chain.clusterConsenter.IsChannelMember(chain.joinBlock); isMem {\n\t\t\tchain.consensusRelation = types.ConsensusRelationConsenter","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/common/follower/follower_chain.go#L162-L198","documentation":"NewChain validates the join block when one is supplied (i.e. joining at a non-genesis block). If joinBlock.Header is nil the block is structurally unusable — the follower needs the header to determine height, configuration, and endpoints — so creation fails immediately.","triggerScenarios":"Calling NewChain (via createFollower or channel participation API 'join' with a join-block) with a joinBlock whose Header field is nil: unmarshaled from corrupt/empty bytes, wrong file provided, or JoinBlock wiring producing an empty block.","commonSituations":"osnadmin channel join supplying a malformed join block file; ledger snapshot/bootstrap code passing a block that failed unmarshaling silently; programming error constructing the JoinBlock in tests.","solutions":["Verify the join block file is a valid, complete block (check protoutil.Unmarshal / unmarshal error handling)","Re-export or re-obtain the join block from a valid source (config block from genesis or an orderer)","Initialize Header and Data on programmatically constructed join blocks","Confirm the block was correctly read from disk (size > 0, not truncated)"],"exampleFix":"// before\nvar joinBlock *common.Block\nproto.Unmarshal(data, joinBlock) // error ignored -> nil Header\nchain, err := follower.NewChain(..., joinBlock, ...)\n// after\njoinBlock := &common.Block{}\nif err := proto.Unmarshal(data, joinBlock); err != nil {\n    return nil, errors.Wrap(err, \"failed unmarshaling join block\")\n}\nif joinBlock.Header == nil {\n    return nil, errors.New(\"join block has nil header\")\n}\nchain, err := follower.NewChain(..., joinBlock, ...)","handlingStrategy":"validation","validationCode":"func validJoinBlock(b *common.Block) error {\n    if b == nil {\n        return errors.New(\"join block is nil\")\n    }\n    if b.Header == nil {\n        return errors.New(\"join block header is nil\")\n    }\n    if b.Data == nil {\n        return errors.New(\"join block data is nil\")\n    }\n    return nil\n}\n// run before follower.NewChain(..., joinBlock, ...)","typeGuard":"func hasHeaderAndData(b *common.Block) bool {\n    return b != nil && b.Header != nil && b.Data != nil\n}","tryCatchPattern":"chain, err := follower.NewChain(..., joinBlock, ...)\nif err != nil {\n    if err.Error() == \"block header is nil\" {\n        return fmt.Errorf(\"invalid join block: re-obtain a complete config block\")\n    }\n    return err\n}","preventionTips":["Check errors from block unmarshaling before passing the block as JoinBlock","Validate join-block files with protoutil before osnadmin channel join","Source join blocks from trusted config blocks, not ad-hoc files","Keep join-block files intact; verify size and readability before use"],"tags":["follower","join-block","validation"],"backgroundTag":"nil-block-header","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"}