hyperledger/fabric · error

cannot get create BlockPuller

Error message

cannot get create BlockPuller

What it means

Raised in BFTSynchronizer.detectTargetHeight when s.BlockPullerFactory.CreateBlockPuller(...) returns an error. The BlockPuller is the client used to probe cluster endpoints and pull blocks; creation failures mean the puller could not even be constructed — usually TLS material or dialer configuration problems, before any network call is attempted.

Source

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

	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")
	}
	defer blockPuller.Close()

	heightByEndpoint, myEndpoint, err := blockPuller.HeightsByEndpoints()
	if err != nil {
		return 0, "", errors.Wrap(err, "cannot get HeightsByEndpoints")
	}

	s.Logger.Infof("HeightsByEndpoints: %+v, my endpoint: %s", heightByEndpoint, myEndpoint)

	delete(heightByEndpoint, myEndpoint)
	var heights []uint64
	for _, value := range heightByEndpoint {
		heights = append(heights, value)
	}

	if len(heights) == 0 {
		return 0, "", errors.New("no cluster members to synchronize with")

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Fix the underlying error returned by CreateBlockPuller (it is wrapped — read the inner message)
  2. Verify cluster.clientCertificate/clientPrivateKey files exist and are readable by the orderer process
  3. Confirm the TLS CA certificate for remote orderers is correctly configured in the channel config
  4. Validate orderer.yaml cluster section against a known-good template

Example fix

// before
cluster:
  serverCertificate:
    File: /nonexistent/tls.crt
// after
cluster:
  serverCertificate:
    File: /var/hyperledger/orderer/tls/server.crt
  serverPrivateKey:
    File: /var/hyperledger/orderer/tls/server.key
Defensive patterns

Strategy: validation

Validate before calling

// Run before starting the orderer / creating the puller
for _, f := range []string{cluster.ServerCertificate.File, cluster.ServerPrivateKey.File} {
    if fi, err := os.Stat(f); err != nil || fi.IsDir() {
        log.Fatalf("cluster TLS file missing or unreadable: %s", f)
    }
}

Try / catch

resp := bftSynchronizer.Sync()
// puller creation is a config error, not transient: detect and stop retrying
if syncFailed(resp) && pullerCreationFailedInLogs() {
    alertOperator("fix cluster TLS configuration; retry will not help")
}

Prevention

When it happens

Trigger: CreateBlockPuller fails with invalid cluster TLS config (missing/invalid cert/key files), predicate dialer misconfiguration, or crypto provider errors — invoked from synchronize during Sync.

Common situations: Bad paths in orderer.yaml cluster TLS settings; unreadable certificate files; wrong SAN/hostname setup; software version mismatch producing incompatible puller configuration.

Related errors


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