hyperledger/fabric · error

collection config package for %s chaincode is not provided

Error message

collection config package for %s chaincode is not provided

What it means

During private data dissemination, the distributor looks up the collection config package for each namespace in the tx's private write set. If the caller-supplied CollectionConfigs map has no entry for a namespace, dissemination cannot proceed, so computeDisseminationPlan aborts with this error.

Source

Thrown at gossip/privdata/distributor.go:166

}

type dissemination struct {
	msg      *protoext.SignedGossipMessage
	criteria gossipgossip.SendCriteria
}

func (d *distributorImpl) computeDisseminationPlan(txID string,
	privDataWithConfig *transientstore.TxPvtReadWriteSetWithConfigInfo,
	blkHt uint64,
) ([]*dissemination, error) {
	privData := privDataWithConfig.PvtRwset
	var disseminationPlan []*dissemination
	for _, pvtRwset := range privData.NsPvtRwset {
		namespace := pvtRwset.Namespace
		configPackage, found := privDataWithConfig.CollectionConfigs[namespace]
		if !found {
			d.logger.Error("Collection config package for", namespace, "chaincode is not provided")
			return nil, errors.New(fmt.Sprint("collection config package for", namespace, "chaincode is not provided"))
		}

		for _, collection := range pvtRwset.CollectionPvtRwset {
			colCP, err := d.getCollectionConfig(configPackage, collection)
			collectionName := collection.CollectionName
			if err != nil {
				d.logger.Error("Could not find collection access policy for", namespace, " and collection", collectionName, "error", err)
				return nil, errors.WithMessage(err, fmt.Sprint("could not find collection access policy for", namespace, " and collection", collectionName, "error", err))
			}

			colAP, err := d.AccessPolicy(colCP, d.chainID)
			if err != nil {
				d.logger.Error("Could not obtain collection access policy, collection name", collectionName, "due to", err)
				return nil, errors.Wrap(err, fmt.Sprint("Could not obtain collection access policy, collection name", collectionName, "due to", err))
			}

			colFilter := colAP.AccessFilter()
			if colFilter == nil {

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Ensure CollectionConfigs is populated for every namespace in NsPvtRwset before calling Distribute
  2. Check that the collection config for the chaincode is committed on the channel and cached on this peer
  3. Verify chaincode/namespace names match exactly between the tx rwset and the config map

Example fix

// before
privDataWithConfig := &privdata.PrivateDataWithConfig{NsPvtRwset: rwset, CollectionConfigs: partialConfigs}
// after
for _, ns := range rwset.NsPvtRwset {
  if _, ok := partialConfigs[ns.Namespace]; !ok { /* fetch config or skip */ }
}
Defensive patterns

Strategy: validation

Validate before calling

for _, ns := range privData.NsPvtRwset {
  if _, ok := privDataWithConfig.CollectionConfigs[ns.Namespace]; !ok {
    return fmt.Errorf("missing collection config for namespace %s", ns.Namespace)
  }
}

Prevention

When it happens

Trigger: Distribute (via computeDisseminationPlan) is called with a privdata object whose CollectionConfigs map lacks a key for a namespace present in NsPvtRwset — e.g. the endorser/config cache did not return configs for that chaincode.

Common situations: Chaincode renamed or namespace mismatch between the rwset and the configs fetched from the ledger; collection config not yet committed/available on this peer; upstream code building privData omitted the namespace.

Related errors


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