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

  1. Inspect the inner wrapped error for the root cause (puller creation vs. height probing)
  2. Verify every consenter has a corresponding, reachable delivery endpoint (1:1 mapping required for BFT sync)
  3. Fix cluster TLS certs/CAs and dialer configuration
  4. 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

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


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