hyperledger/fabric · error

cannot create BFT block deliverer

Error message

cannot create BFT block deliverer

What it means

Raised in BFTSynchronizer.synchronize when s.createBFTDeliverer(startHeight, myEndpoint) returns an error, wrapped as 'cannot create BFT block deliverer'. The BFT deliverer wires up the block-fetching machinery (BlockPuller/deliver clients) that streams blocks into the sync buffer; creation failures are configuration, TLS, or dialing problems detected before fetching starts.

Source

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

	if err != nil {
		return nil, errors.Wrapf(err, "cannot get detect target height")
	}

	startHeight := s.Support.Height()
	if startHeight >= targetHeight {
		return nil, errors.Errorf("already at target height of %d", targetHeight)
	}

	// === 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.

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Read the wrapped inner error to see whether it is a TLS, dialer, or crypto failure
  2. Validate orderer.yaml cluster settings: TLS.Enabled, client cert/key paths, dial timeouts
  3. Ensure the cluster client certificate/key pair is valid and its CA is trusted in the channel config
  4. Compare with a working node's configuration and fix deviations

Example fix

// before (orderer.yaml)
cluster:
  clientCertificate:
    File: wrong-path.pem
// after
cluster:
  clientCertificate:
    File: /var/hyperledger/orderer/tls/server.crt
  clientPrivateKey:
    File: /var/hyperledger/orderer/tls/server.key
Defensive patterns

Strategy: validation

Validate before calling

// Validate cluster config before starting the orderer
if _, err := tls.LoadX509KeyPair(cluster.ClientCertificate.File, cluster.ClientPrivateKey.File); err != nil {
    log.Fatalf("invalid cluster client keypair: %v", err)
}

Try / catch

resp := bftSynchronizer.Sync()
// creation failures are deterministic (config), not retriable — fail fast and alert
if syncFailed(resp) && delivererCreationFailedInLogs() {
    alertOperator("BFT deliverer creation failed: fix orderer.yaml cluster section")
}

Prevention

When it happens

Trigger: createBFTDeliverer fails while constructing the deliverer: BlockPuller creation errors (invalid cluster TLS config, dialer misconfiguration, crypto provider issues) — happens after target height detection succeeded but before DeliverBlocks is started.

Common situations: Malformed orderer.yaml cluster section (bad TLS cert/key paths, wrong dial timeout); missing or invalid MSP/TLS material for the cluster client; earlier height probing passed but deliverer-specific configuration is wrong.

Related errors


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