hyperledger/fabric · error

error getting private data by block number %d

Error message

error getting private data by block number %d

What it means

After obtaining the channel ledger, getPrivateData calls GetPvtDataByNum(blockNum) to retrieve private data for the block. If the ledger returns an error (ledger internal failure, block not yet committed to pvt store, etc.), it is wrapped with this message naming the block number and returned to the deliver client.

Source

Thrown at core/peer/deliverevents.go:188

	return "block_and_pvtdata"
}

// getPrivateData returns private data for the block
func (bprs *blockAndPrivateDataResponseSender) getPrivateData(
	block *common.Block,
	chain deliver.Chain,
	channelID string,
	signedData *protoutil.SignedData,
) (map[uint64]*rwset.TxPvtReadWriteSet, error) {
	channel, ok := chain.(Chain)
	if !ok {
		return nil, errors.New("wrong chain type")
	}

	pvtData, err := channel.Ledger().GetPvtDataByNum(block.Header.Number, nil)
	if err != nil {
		logger.Errorf("Error getting private data by block number %d on channel %s", block.Header.Number, channelID)
		return nil, errors.Wrapf(err, "error getting private data by block number %d", block.Header.Number)
	}

	seqs2Namespaces := aggregatedCollections(make(map[seqAndDataModel]map[string][]*rwset.CollectionPvtReadWriteSet))

	configHistoryRetriever, err := channel.Ledger().GetConfigHistoryRetriever()
	if err != nil {
		return nil, err
	}

	identityDeserializer, err := bprs.IdentityDeserializerManager.Deserializer(channelID)
	if err != nil {
		return nil, err
	}

	// check policy for each collection and add the collection if passing the policy requirement
	for _, item := range pvtData {
		logger.Debugf("Got private data for block number %d, tx sequence %d", block.Header.Number, item.SeqInBlock)
		if item.WriteSet == nil {

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Check the wrapped cause (errors.Cause / %v chain) for the underlying ledger error and address it (e.g., corrupted DB → rebuild).
  2. Request pvt data only for blocks within the private-data retention window (BTL not expired).
  3. Retry after the block's private data has been committed if the request raced commit.
  4. Verify peer logs for the accompanying 'Error getting private data by block number' line to identify the channel/block.

Example fix

// before
pvt, err := getPrivateData(block, chain, chID, sd) // may fail for purged data
// after
pvt, err := getPrivateData(block, chain, chID, sd)
if err != nil {
  var cause error
  if unwrapped := errors.Unwrap(err); unwrapped != nil { cause = unwrapped }
  log.Printf("pvt data unavailable for block %d: %v", block.Header.Number, cause)
}
Defensive patterns

Strategy: retry

Validate before calling

if block.Header != nil && block.Header.Number >= latestCommittedHeight {
  return errors.New("block not committed yet; defer pvt data request")
}

Try / catch

pvt, err := getPrivateData(block, chain, chID, sd)
if err != nil && strings.Contains(err.Error(), "error getting private data by block number") {
  // inspect errors.Unwrap(err); retry with backoff or trigger reconciliation
}

Prevention

When it happens

Trigger: SendBlockResponse with reconciliation enabled requesting private data for a block number whose private data is unavailable or whose ledger/pvtdata store errors (e.g., blockNum beyond committed pvt data, corrupted pvt store).

Common situations: Requesting pvt data for a very recent block not yet in the private data store; peer's pvtdata store partially purged (BTL expired); ledger database corruption; requesting an old block after pvtdata expiry.

Related errors


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