hyperledger/fabric · error

failed to get any blocks from SyncBuffer

Error message

failed to get any blocks from SyncBuffer

What it means

Raised in BFTSynchronizer.synchronize when s.getBlocksFromSyncBuffer(startHeight, targetHeight) returns an error — the BFTDeliverer goroutine was started but the sync buffer yielded no usable blocks, so block replication failed entirely. The message is slightly misleading: it wraps any error from the buffer consumption loop, not only an empty buffer.

Source

Thrown at orderer/consensus/smartbft/synchronizer_bft.go:118

	// === Create a buffer to accept the blocks delivered from the BFTDeliverer.
	capacityBlocks := max(uint(s.LocalConfigCluster.ReplicationBufferSize)/uint(s.Support.SharedConfig().BatchSize().AbsoluteMaxBytes), 100)
	s.mutex.Lock()
	s.syncBuff = NewSyncBuffer(capacityBlocks)
	s.mutex.Unlock()

	// === Create the BFT block deliverer and start a go-routine that fetches block and inserts them into the syncBuffer.
	bftDeliverer, err := s.createBFTDeliverer(startHeight, myEndpoint)
	if err != nil {
		return nil, errors.Wrapf(err, "cannot create BFT block deliverer")
	}

	go bftDeliverer.DeliverBlocks()
	defer bftDeliverer.Stop()

	// === Loop on sync-buffer and pull blocks, writing them to the ledger, returning the last block pulled.
	lastPulledBlock, err := s.getBlocksFromSyncBuffer(startHeight, targetHeight)
	if err != nil {
		return nil, errors.Wrapf(err, "failed to get any blocks from SyncBuffer")
	}

	decision := s.BlockToDecision(lastPulledBlock)
	s.Logger.Infof("Returning decision from block [%d], decision: %+v", lastPulledBlock.GetHeader().GetNumber(), decision)
	return decision, nil
}

// detectTargetHeight probes remote endpoints and detects what is the target height this node needs to reach. It also
// detects the self-endpoint.
//
// In BFT it is highly recommended that the channel/orderer-endpoints (for delivery & broadcast) map 1:1 to the
// channel/orderers/consenters (for cluster consensus), that is, every consenter should be represented by a
// delivery endpoint. This important for Sync to work properly.
func (s *BFTSynchronizer) detectTargetHeight() (uint64, string, error) {
	blockPuller, err := s.BlockPullerFactory.CreateBlockPuller(s.Support, s.ClusterDialer, s.LocalConfigCluster, s.CryptoProvider)
	if err != nil {
		return 0, "", errors.Wrap(err, "cannot get create BlockPuller")
	}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Look at deliverer logs just before this error for the real failure (deliver stream error, buffer close cause)
  2. Verify remote peers are reachable over the cluster port and hold blocks from startHeight onward
  3. Fix TLS/authorization for the Deliver service and retry synchronization
  4. Check local disk space and ledger health if the failure occurred on WriteBlock
Defensive patterns

Strategy: retry

Validate before calling

// Ensure peers hold the full needed range before syncing
startHeight := support.Height()
if minPeerHeight(consenters) < startHeight+1 || maxPeerHeight(consenters) < startHeight+1 {
    // no peer can serve the first needed block yet
}

Try / catch

resp := bftSynchronizer.Sync()
if syncFailed(resp) {
    // transient deliver/buffer failure — retry with backoff
    time.Sleep(backoff)
    resp = bftSynchronizer.Sync()
}

Prevention

When it happens

Trigger: DeliverBlocks runs but fails to push any block into s.syncBuff (all deliver connections fail, remote peers reject the range, context cancelled), or getBlocksFromSyncBuffer aborts (buffer closed early, expected sequence mismatch, ledger write failure on the first block).

Common situations: Network interruption right after sync starts; remote peers rejecting Deliver due to TLS/certificate auth; peers not holding blocks in [startHeight, targetHeight); sync buffer closed because the deliverer hit a fatal error; ledger write errors (disk full).

Related errors


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