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
- Check the wrapped cause (errors.Cause / %v chain) for the underlying ledger error and address it (e.g., corrupted DB → rebuild).
- Request pvt data only for blocks within the private-data retention window (BTL not expired).
- Retry after the block's private data has been committed if the request raced commit.
- 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
- Respect BTL retention windows
- Avoid racing pvt data requests against commit
- Monitor pvtdata store health
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
- unable to check whether collection existed earlier for chain
- wrong chain type
- failed to commit private data
- envelope has no header
- channel header in envelope must contain timestamp
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/5b3a344458b891be.
Report an issue: GitHub.