hyperledger/fabric · error

no collection config update below block sequence =

Error message

no collection config update below block sequence = %d for chaincode %s is available

What it means

MostRecentCollectionConfigBelow succeeded but returned a nil configInfo, so the config history service has no collection config update record below the requested block sequence. This is a distinct 'record absent' condition from the errored lookup in [1392].

Solutions

  1. Ensure the collection config update block is present and below the block being reconciled.
  2. Reconcile only newer blocks, or commit the collection config update again so a record exists below the target block.
  3. Check/rebuild the config history index on the peer.
  4. Verify the chaincode name is spelled exactly as deployed.
Defensive patterns

Strategy: validation

Validate before calling

configInfo, err := retriever.MostRecentCollectionConfigBelow(blockNum, chaincodeName)
if err != nil || configInfo == nil {
    log.Warningf("no collection config below block %d for %s", blockNum, chaincodeName)
    return // skip reconciliation for these digs
}

Try / catch

if err != nil {
    if strings.Contains(err.Error(), "no collection config update below") {
        log.Warningf("collection config predates block %d; cannot reconcile", blockNum)
        return
    }
    return err
}

Prevention

When it happens

Trigger: getMostRecentCollectionConfig (via getDig2CollectionConfig) when configHistoryRetriever.MostRecentCollectionConfigBelow returns (nil, nil) for the given chaincodeName and blockNum.

Common situations: Reconciling private data for blocks committed before the chaincode/collection was first defined; a peer whose ledger history index lacks entries for that chaincode (e.g. joined via snapshot that excludes old config history).

Related errors


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

Appendix: source

Thrown at gossip/privdata/reconcile.go:244

				dig2collectionCfg[digKey] = collectionConfigCache[collConfigKey]
			}
		}
	}
	return dig2collectionCfg, minBlock, maxBlock
}

func (r *Reconciler) getMostRecentCollectionConfig(chaincodeName string, collectionName string, blockNum uint64) (*peer.StaticCollectionConfig, error) {
	configHistoryRetriever, err := r.GetConfigHistoryRetriever()
	if err != nil {
		return nil, errors.Wrap(err, "configHistoryRetriever is not available")
	}

	configInfo, err := configHistoryRetriever.MostRecentCollectionConfigBelow(blockNum, chaincodeName)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("cannot find recent collection config update below block sequence = %d for chaincode %s", blockNum, chaincodeName))
	}
	if configInfo == nil {
		return nil, errors.New(fmt.Sprintf("no collection config update below block sequence = %d for chaincode %s is available", blockNum, chaincodeName))
	}

	collectionConfig := extractCollectionConfig(configInfo.CollectionConfig, collectionName)
	if collectionConfig == nil {
		return nil, errors.New(fmt.Sprintf("no collection config was found for collection %s for chaincode %s", collectionName, chaincodeName))
	}

	staticCollectionConfig, wasCastingSuccessful := collectionConfig.Payload.(*peer.CollectionConfig_StaticCollectionConfig)
	if !wasCastingSuccessful {
		return nil, errors.New(fmt.Sprintf("expected collection config of type CollectionConfig_StaticCollectionConfig for collection %s for chaincode %s, while got different config type...", collectionName, chaincodeName))
	}
	return staticCollectionConfig.StaticCollectionConfig, nil
}

func (r *Reconciler) preparePvtDataToCommit(elements []*protosgossip.PvtDataElement) []*ledger.ReconciledPvtdata {
	rwSetByBlockByKeys := r.groupRwsetByBlock(elements)

	// populate the private RWSets passed to the ledger

View on GitHub (pinned to 2736b63f8f)