{"record":{"id":"77d1704ab6128305","repo":"hyperledger/fabric","slug":"block-number-should-have-been-d-but-was-d","errorCode":null,"errorMessage":"block number should have been %d but was %d","messagePattern":"block number should have been (.+?) but was (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/ledger/blkstorage/blockfile_mgr.go","lineNumber":287,"sourceCode":"\tnextFileWriter, err := newBlockfileWriter(\n\t\tderiveBlockfilePath(mgr.rootDir, blkfilesInfo.latestFileNumber),\n\t)\n\tif err != nil {\n\t\tpanic(fmt.Sprintf(\"Could not open writer to next file: %s\", err))\n\t}\n\tmgr.currentFileWriter.close()\n\terr = mgr.saveBlkfilesInfo(blkfilesInfo, true)\n\tif err != nil {\n\t\tpanic(fmt.Sprintf(\"Could not save next block file info to db: %s\", err))\n\t}\n\tmgr.currentFileWriter = nextFileWriter\n\tmgr.updateBlockfilesInfo(blkfilesInfo)\n}\n\nfunc (mgr *blockfileMgr) addBlock(block *common.Block) error {\n\tbcInfo := mgr.getBlockchainInfo()\n\tif block.Header.Number != bcInfo.Height {\n\t\treturn errors.Errorf(\n\t\t\t\"block number should have been %d but was %d\",\n\t\t\tmgr.getBlockchainInfo().Height, block.Header.Number,\n\t\t)\n\t}\n\n\t// Add the previous hash check - Though, not essential but may not be a bad idea to\n\t// verify the field `block.Header.PreviousHash` present in the block.\n\t// This check is a simple bytes comparison and hence does not cause any observable performance penalty\n\t// and may help in detecting a rare scenario if there is any bug in the ordering service.\n\tif !bytes.Equal(block.Header.PreviousHash, bcInfo.CurrentBlockHash) {\n\t\treturn errors.Errorf(\n\t\t\t\"unexpected Previous block hash. Expected PreviousHash = [%x], PreviousHash referred in the latest block= [%x]\",\n\t\t\tbcInfo.CurrentBlockHash, block.Header.PreviousHash,\n\t\t)\n\t}\n\tblockBytes, info := serializeBlock(block)\n\tblockHash := protoutil.BlockHeaderHash(block.Header)\n\t// Get the location / offset where each transaction starts in the block and where the block ends","sourceCodeStart":269,"sourceCodeEnd":305,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/common/ledger/blkstorage/blockfile_mgr.go#L269-L305","documentation":"addBlock enforces that the incoming block's Header.Number equals the current ledger height (next expected block number). If the block is a duplicate (number < height), out of order, or skipping ahead (number > height), it returns this error and the block is not committed.","triggerScenarios":"Calling AddBlock with a block whose Header.Number != current height — re-committing an already-committed block, delivering blocks out of order, or gaps in the block sequence from a misbehaving deliverer.","commonSituations":"Deliver/gossip client reconnecting and replaying blocks already committed; a committer receiving a block range that overlaps local height after a ledger reset; ordering-service bugs producing block gaps; application code driving the ledger API directly with wrong numbering.","solutions":["Skip blocks with number less than the current ledger height (query GetBlockchainInfo first) instead of re-adding","If height is behind, re-sync from a correct source starting exactly at bcInfo.Height","Fix the block producer/orderer to avoid gaps; investigate ordering service for skipped numbers","If the ledger is wrong/stuck, reset and re-sync the ledger rather than forcing mismatched blocks"],"exampleFix":"// before: blindly adds every delivered block\nfor _, blk := range blocks {\n    if err := store.AddBlock(blk); err != nil { return err }\n}\n// after: skip already-committed blocks\nbcInfo, _ := store.GetBlockchainInfo()\nfor _, blk := range blocks {\n    if blk.Header.Number < bcInfo.Height { continue }\n    if err := store.AddBlock(blk); err != nil { return err }\n}","handlingStrategy":"validation","validationCode":"bcInfo, err := store.GetBlockchainInfo()\nif err != nil { return err }\nif block.Header.Number < bcInfo.Height {\n    return nil // duplicate: already committed, skip\n}\nif block.Header.Number > bcInfo.Height {\n    return fmt.Errorf(\"gap: expected %d, got %d\", bcInfo.Height, block.Header.Number)\n}","typeGuard":null,"tryCatchPattern":"if err := store.AddBlock(block); err != nil {\n    if strings.Contains(err.Error(), \"block number should have been\") {\n        // refresh bcInfo and skip/re-sync instead of failing the whole stream\n    }\n    return err\n}","preventionTips":["Query GetBlockchainInfo before committing and skip duplicates","Consume blocks strictly in order from a single ordered source","After ledger resets, restart block consumption from the new height","Monitor for ordering-service gaps (numbers skipping) and alert early"],"tags":["hyperledger-fabric","ledger","block-number","sequence","consistency"],"backgroundTag":"block-number-mismatch","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"}