hyperledger/fabric · error

no collection config update below block sequence = %d for ch

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].

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)

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.