hyperledger/fabric · error
cannot find recent collection config update below block sequ
Error message
cannot find recent collection config update below block sequence = %d, collection name = <%s> for chaincode <%s>
What it means
MostRecentCollectionConfigBelow searches the collection-config history for the latest configuration recorded before the given block sequence. If it returns an error, the retriever wraps it as 'cannot find recent collection config update below block sequence ...'. Without a historical config, the pvt-data access policy cannot be evaluated for the old transaction.
Source
Thrown at gossip/privdata/dataretriever.go:147
// private data doesn't hold rwsets for namespace and collection or
// belongs to different transaction
if !data.Has(dig.Namespace, dig.Collection) || data.SeqInBlock != dig.SeqInBlock {
continue
}
pvtRWSet := dr.extractPvtRWsets(data.WriteSet.NsPvtRwset, dig.Namespace, dig.Collection)
pvtRWSetWithConfig.RWSet = append(pvtRWSetWithConfig.RWSet, pvtRWSet...)
}
confHistoryRetriever, err := dr.committer.GetConfigHistoryRetriever()
if err != nil {
return nil, errors.Errorf("cannot obtain configuration history retriever, for collection <%s>"+
" txID <%s> block sequence number <%d> due to <%s>", dig.Collection, dig.TxId, dig.BlockSeq, err)
}
configInfo, err := confHistoryRetriever.MostRecentCollectionConfigBelow(dig.BlockSeq, dig.Namespace)
if err != nil {
return nil, errors.Errorf("cannot find recent collection config update below block sequence = %d,"+
" collection name = <%s> for chaincode <%s>", dig.BlockSeq, dig.Collection, dig.Namespace)
}
if configInfo == nil {
return nil, errors.Errorf("no collection config update below block sequence = <%d>"+
" collection name = <%s> for chaincode <%s> is available ", dig.BlockSeq, dig.Collection, dig.Namespace)
}
configs := extractCollectionConfig(configInfo.CollectionConfig, dig.Collection)
if configs == nil {
return nil, errors.Errorf("no collection config was found for collection <%s>"+
" namespace <%s> txID <%s>", dig.Collection, dig.Namespace, dig.TxId)
}
pvtRWSetWithConfig.CollectionConfig = configs
results[common.DigKey{
Namespace: dig.Namespace,
Collection: dig.Collection,
TxId: dig.TxId,
BlockSeq: dig.BlockSeq,View on GitHub (pinned to 2736b63f8f)
Solutions
- Verify the collection config update event exists at/below that block in the config history DB.
- Rebuild the peer databases (`peer node rebuild-dbs`) after restoring from a full, consistent backup.
- Re-fetch private data from another peer that has complete config history.
- If data was purged by retention policy, restore it or rely on reconciliation from a peer with full history.
Example fix
// before: hard failure on missing config
configInfo, err := confHistoryRetriever.MostRecentCollectionConfigBelow(dig.BlockSeq, dig.Namespace)
// after: skip digest when history is missing
configInfo, err := confHistoryRetriever.MostRecentCollectionConfigBelow(dig.BlockSeq, dig.Namespace)
if err != nil {
logger.Warningf("no config history for %s at seq %d, skipping", dig.Namespace, dig.BlockSeq)
continue
} Defensive patterns
Strategy: fallback
Validate before calling
retriever, err := committer.GetConfigHistoryRetriever()
if err == nil {
if _, err := retriever.MostRecentCollectionConfigBelow(dig.BlockSeq, dig.Namespace); err != nil {
logger.Warningf("no config below seq %d for %s", dig.BlockSeq, dig.Namespace)
}
} Type guard
func hasConfigBelow(r ledger.ConfigHistoryRetriever, seq uint64, ns string) bool {
_, err := r.MostRecentCollectionConfigBelow(seq, ns)
return err == nil
} Try / catch
configInfo, err := retriever.MostRecentCollectionConfigBelow(dig.BlockSeq, dig.Namespace)
if err != nil {
logger.Warningf("falling back to another peer for pvt data of %s@%d", dig.Namespace, dig.BlockSeq)
return fallbackFetch(dig)
} Prevention
- Never restore peer DBs from partial backups — config history must be complete.
- Only request pvt data at block heights where the collection was already defined.
- Avoid purging config history for old blocks still under reconciliation.
- Verify collection lifecycle ordering: config update commit before pvt-data requests.
When it happens
Trigger: ConfHistoryRetriever.MostRecentCollectionConfigBelow(dig.BlockSeq, dig.Namespace) errors — usually the config history DB lacks entries (history wasn't recorded for that range) or the DB read fails.
Common situations: Private data requested for a very old transaction whose config history was purged; config history DB missing records after a restore from a partial backup; requesting data for a collection that had no config at that block height.
Related errors
- collection-name: %s -- cannot unmarshal identity bytes into
- collection-name: %s -- collection member '%s' is not part of
- collection-name: %s -- cannot unmarshal identity bytes into
- collection-name: %s -- principal type %v is not supported
- signature policy is not an OR concatenation, NOutOf %d
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/91a961456dcd40e4.
Report an issue: GitHub.