{"record":{"id":"3d79be832b048dbb","repo":"hyperledger/fabric","slug":"no-collection-config-update-below-block-sequence","errorCode":null,"errorMessage":"no collection config update below block sequence = <%d> collection name = <%s> for chaincode <%s> is available ","messagePattern":"no collection config update below block sequence = <(.+?)> collection name = <(.+?)> for chaincode <(.+?)> is available ","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gossip/privdata/dataretriever.go","lineNumber":152,"sourceCode":"\n\t\t\tpvtRWSet := dr.extractPvtRWsets(data.WriteSet.NsPvtRwset, dig.Namespace, dig.Collection)\n\t\t\tpvtRWSetWithConfig.RWSet = append(pvtRWSetWithConfig.RWSet, pvtRWSet...)\n\t\t}\n\n\t\tconfHistoryRetriever, err := dr.committer.GetConfigHistoryRetriever()\n\t\tif err != nil {\n\t\t\treturn nil, errors.Errorf(\"cannot obtain configuration history retriever, for collection <%s>\"+\n\t\t\t\t\" txID <%s> block sequence number <%d> due to <%s>\", dig.Collection, dig.TxId, dig.BlockSeq, err)\n\t\t}\n\n\t\tconfigInfo, err := confHistoryRetriever.MostRecentCollectionConfigBelow(dig.BlockSeq, dig.Namespace)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Errorf(\"cannot find recent collection config update below block sequence = %d,\"+\n\t\t\t\t\" collection name = <%s> for chaincode <%s>\", dig.BlockSeq, dig.Collection, dig.Namespace)\n\t\t}\n\n\t\tif configInfo == nil {\n\t\t\treturn nil, errors.Errorf(\"no collection config update below block sequence = <%d>\"+\n\t\t\t\t\" collection name = <%s> for chaincode <%s> is available \", dig.BlockSeq, dig.Collection, dig.Namespace)\n\t\t}\n\t\tconfigs := extractCollectionConfig(configInfo.CollectionConfig, dig.Collection)\n\t\tif configs == nil {\n\t\t\treturn nil, errors.Errorf(\"no collection config was found for collection <%s>\"+\n\t\t\t\t\" namespace <%s> txID <%s>\", dig.Collection, dig.Namespace, dig.TxId)\n\t\t}\n\t\tpvtRWSetWithConfig.CollectionConfig = configs\n\t\tresults[common.DigKey{\n\t\t\tNamespace:  dig.Namespace,\n\t\t\tCollection: dig.Collection,\n\t\t\tTxId:       dig.TxId,\n\t\t\tBlockSeq:   dig.BlockSeq,\n\t\t\tSeqInBlock: dig.SeqInBlock,\n\t\t}] = pvtRWSetWithConfig\n\t}\n\n\treturn results, nil","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/gossip/privdata/dataretriever.go#L134-L170","documentation":"After querying the config history, if MostRecentCollectionConfigBelow returns successfully but with nil configInfo, the retriever reports that no collection config update exists below the requested block sequence. The access policy for the private data cannot be reconstructed, so the request is rejected rather than answered with the wrong policy.","triggerScenarios":"Requesting private data for a digest whose BlockSeq precedes the first collection-config update for that chaincode/collection — e.g. the collection was introduced by a chaincode upgrade at a later block than the transaction being reconciled.","commonSituations":"Reconciliation of pvt data for blocks older than when the private collection was defined; peers restored from partial backups missing early config history; miscomputed BlockSeq in gossip digests.","solutions":["Confirm the collection was defined (chaincode upgraded with the collection config) before the requested blockSeq; don't request pvt data for earlier blocks.","Use the block where the collection config was first committed as the lower bound for reconciliation.","Re-sync config history from genesis by rebuilding peer DBs from a consistent backup.","Fetch the data from a peer holding the correct historical config."],"exampleFix":"// before\nconfigInfo, err := confHistoryRetriever.MostRecentCollectionConfigBelow(dig.BlockSeq, dig.Namespace)\n\n// after: check digest is newer than collection creation\nif dig.BlockSeq < collectionCreatedAtSeq(dig.Namespace, dig.Collection) {\n    return nil, nil // collection didn't exist then\n}\nconfigInfo, err := confHistoryRetriever.MostRecentCollectionConfigBelow(dig.BlockSeq, dig.Namespace)","handlingStrategy":"validation","validationCode":"creationSeq, ok := collectionCreationBlockSeq(ns, collection)\nif !ok || dig.BlockSeq <= creationSeq {\n    return errors.New(\"collection not defined at requested block sequence\")\n}","typeGuard":"func collectionDefinedAt(ns, coll string, seq uint64) bool {\n    cs, ok := collectionCreationBlockSeq(ns, coll)\n    return ok && seq > cs\n}","tryCatchPattern":"configInfo, err := retriever.MostRecentCollectionConfigBelow(dig.BlockSeq, dig.Namespace)\nif configInfo == nil {\n    logger.Debugf(\"collection %s not defined below seq %d; skipping digest\", dig.Collection, dig.BlockSeq)\n    return\n}","preventionTips":["Start reconciliation from the block where the collection was first configured.","Keep config history from genesis (full backups only).","Don't request pvt data predating the collection's chaincode upgrade.","Track collection creation heights in tooling that builds digests."],"tags":["fabric","collection-config","private-data","reconciliation"],"backgroundTag":"collection-config-history-missing","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}