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

  1. Verify the collection config update event exists at/below that block in the config history DB.
  2. Rebuild the peer databases (`peer node rebuild-dbs`) after restoring from a full, consistent backup.
  3. Re-fetch private data from another peer that has complete config history.
  4. 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

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


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