hyperledger/fabric · error

unable to retrieve last config block [%d]

Error message

unable to retrieve last config block [%d]

What it means

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.

Source

Thrown at orderer/common/cluster/util.go:526

	// or nil if such a block doesn't exist.
	Block(number uint64) *common.Block
}

// LastConfigBlock returns the last config block relative to the given block.
func LastConfigBlock(block *common.Block, blockRetriever BlockRetriever) (*common.Block, error) {
	if block == nil {
		return nil, errors.New("nil block")
	}
	if blockRetriever == nil {
		return nil, errors.New("nil blockRetriever")
	}
	lastConfigBlockNum, err := protoutil.GetLastConfigIndexFromBlock(block)
	if err != nil {
		return nil, err
	}
	lastConfigBlock := blockRetriever.Block(lastConfigBlockNum)
	if lastConfigBlock == nil {
		return nil, errors.Errorf("unable to retrieve last config block [%d]", lastConfigBlockNum)
	}
	return lastConfigBlock, nil
}

// StreamCountReporter reports the number of streams currently connected to this node
type StreamCountReporter struct {
	Metrics *Metrics
	count   uint32
}

func (scr *StreamCountReporter) Increment() {
	count := atomic.AddUint32(&scr.count, 1)
	scr.Metrics.reportStreamCount(count)
}

func (scr *StreamCountReporter) Decrement() {
	count := atomic.AddUint32(&scr.count, ^uint32(0))
	scr.Metrics.reportStreamCount(count)

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Allow the block puller to catch up, or pull the missing block from another orderer before retrying.
  2. Check the retriever's block availability (ledger height vs. lastConfigBlockNum) and storage health.
  3. Restart the ordering node so onboarding/replay of the channel ledger occurs.
  4. Restore from a snapshot or rejoin the channel if ledger data was permanently lost.
Defensive patterns

Strategy: retry

Validate before calling

// Check local availability before requesting the last config block
if retriever.Height() <= lastConfigBlockNum {
    return errors.New("last config block not yet available locally")
}

Try / catch

blk, err := cluster.LastConfigBlock(block, retriever)
if err != nil {
    if strings.Contains(err.Error(), "unable to retrieve last config block") {
        time.Sleep(pullRetryInterval)
        return retryLastConfigBlock(block, retriever)
    }
    return err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/60b3c6639fc0d555. Report an issue: GitHub.