{"record":{"id":"60b3c6639fc0d555","repo":"hyperledger/fabric","slug":"unable-to-retrieve-last-config-block-d","errorCode":null,"errorMessage":"unable to retrieve last config block [%d]","messagePattern":"unable to retrieve last config block \\[(.+?)\\]","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"orderer/common/cluster/util.go","lineNumber":526,"sourceCode":"\t// or nil if such a block doesn't exist.\n\tBlock(number uint64) *common.Block\n}\n\n// LastConfigBlock returns the last config block relative to the given block.\nfunc LastConfigBlock(block *common.Block, blockRetriever BlockRetriever) (*common.Block, error) {\n\tif block == nil {\n\t\treturn nil, errors.New(\"nil block\")\n\t}\n\tif blockRetriever == nil {\n\t\treturn nil, errors.New(\"nil blockRetriever\")\n\t}\n\tlastConfigBlockNum, err := protoutil.GetLastConfigIndexFromBlock(block)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tlastConfigBlock := blockRetriever.Block(lastConfigBlockNum)\n\tif lastConfigBlock == nil {\n\t\treturn nil, errors.Errorf(\"unable to retrieve last config block [%d]\", lastConfigBlockNum)\n\t}\n\treturn lastConfigBlock, nil\n}\n\n// StreamCountReporter reports the number of streams currently connected to this node\ntype StreamCountReporter struct {\n\tMetrics *Metrics\n\tcount   uint32\n}\n\nfunc (scr *StreamCountReporter) Increment() {\n\tcount := atomic.AddUint32(&scr.count, 1)\n\tscr.Metrics.reportStreamCount(count)\n}\n\nfunc (scr *StreamCountReporter) Decrement() {\n\tcount := atomic.AddUint32(&scr.count, ^uint32(0))\n\tscr.Metrics.reportStreamCount(count)","sourceCodeStart":508,"sourceCodeEnd":544,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/common/cluster/util.go#L508-L544","documentation":"LastConfigBlock reads the last-config index from a config block and then asks the BlockRetriever (cluster service's block store abstraction) for that block number. If the retriever returns nil — the block is not available locally yet — this error reports the missing index.","triggerScenarios":"Calling LastConfigBlock when blockRetriever.Block(lastConfigBlockNum) returns nil, e.g. the orderer has not yet pulled/retained the referenced last-config block, or the ledger was pruned below that height.","commonSituations":"A freshly started or catching-up orderer whose local ledger lacks older config blocks, BFT-puller bootstrapping before the needed block arrives, ledger files corrupted or manually trimmed.","solutions":["Allow the block puller to catch up, or pull the missing block from another orderer before retrying.","Check the retriever's block availability (ledger height vs. lastConfigBlockNum) and storage health.","Restart the ordering node so onboarding/replay of the channel ledger occurs.","Restore from a snapshot or rejoin the channel if ledger data was permanently lost."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Check local availability before requesting the last config block\nif retriever.Height() <= lastConfigBlockNum {\n    return errors.New(\"last config block not yet available locally\")\n}","typeGuard":null,"tryCatchPattern":"blk, err := cluster.LastConfigBlock(block, retriever)\nif err != nil {\n    if strings.Contains(err.Error(), \"unable to retrieve last config block\") {\n        time.Sleep(pullRetryInterval)\n        return retryLastConfigBlock(block, retriever)\n    }\n    return err\n}","preventionTips":["Let newly joined orderers finish onboarding/catch-up before serving verification requests.","Monitor ledger height across the ordering cluster.","Never manually delete or trim orderer ledger files."],"tags":["fabric","ledger","block-retrieval","orderer"],"backgroundTag":"block-not-available","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"}