hyperledger/fabric · error
cannot get detect target height
Error message
cannot get detect target height
What it means
Raised in BFTSynchronizer.synchronize when detectTargetHeight() returns an error, wrapped with 'cannot get detect target height'. detectTargetHeight probes all cluster delivery endpoints (via a BlockPuller) to compute the target height and identify this node's own endpoint; any failure creating the puller or probing heights surfaces here.
Source
Thrown at orderer/consensus/smartbft/synchronizer_bft.go:92
CurrentConfig: s.lastReconfig.CurrentConfig,
CurrentNodes: s.lastReconfig.CurrentNodes,
},
}
}
// Buffer return the internal SyncBuffer for testability.
func (s *BFTSynchronizer) Buffer() *SyncBuffer {
s.mutex.Lock()
defer s.mutex.Unlock()
return s.syncBuff
}
func (s *BFTSynchronizer) synchronize() (*types.Decision, error) {
// === We probe all the endpoints and establish a target height, as well as detect the self endpoint.
targetHeight, myEndpoint, err := s.detectTargetHeight()
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")
}View on GitHub (pinned to 2736b63f8f)
Solutions
- Inspect the inner wrapped error for the root cause (puller creation vs. height probing)
- Verify every consenter has a corresponding, reachable delivery endpoint (1:1 mapping required for BFT sync)
- Fix cluster TLS certs/CAs and dialer configuration
- Restore quorum: bring enough orderers online so height probing succeeds
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check: every consenter must map to a reachable delivery endpoint
for _, c := range sharedConfig.Consenters() {
if !reachable(c.Host, c.Port, tlsConf) {
log.Printf("BFT sync will fail: endpoint %s:%s unreachable", c.Host, c.Port)
}
} Try / catch
resp := bftSynchronizer.Sync()
// On error the SyncResponse is built from the local ledger; detect and retry later
if resp.Latest.Height <= localHeight && quorumOffline() {
scheduleRetrySync(backoff)
} Prevention
- Maintain a strict 1:1 mapping between consenters and delivery endpoints in channel config
- Monitor cluster-port reachability for all BFT nodes
- Keep TLS certificates and CAs in sync across the cluster
- Restore quorum quickly with automated alerting on orderer downtime
When it happens
Trigger: BFTSynchronizer.Sync -> synchronize -> detectTargetHeight fails: CreateBlockPuller errors (bad TLS/dialer config) or HeightsByEndpoints errors (all remote endpoints unreachable, Deliver failures).
Common situations: Cluster peers down or partitioned during leader election/catch-up; TLS misconfiguration in the cluster section; consenter endpoints in channel config not mapping 1:1 to delivery endpoints (explicitly warned against in the source comment); DNS/firewall issues on the cluster port.
Related errors
- cannot get HeightsByEndpoints
- no cluster members to synchronize with
- failed pulling block %d
- failed to get any blocks from SyncBuffer
- cannot get HeightsByEndpoints
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/58e90231c498979e.
Report an issue: GitHub.