hyperledger/fabric · error

no configuration for collection

Error message

no configuration for collection %s found

What it means

getCollectionConfig scans the CollectionConfigPackage for a static collection config whose name matches the collection in the private rwset. If none matches, it returns this error, aborting dissemination for that namespace.

Solutions

  1. Ensure the collection name in PutPrivateData matches a collection defined in the chaincode's collection config
  2. If the collection was removed/renamed via collection config update, accept that old data can no longer be disseminated or restore the collection definition
  3. Re-commit a collection config containing the missing collection

Example fix

// before
err := stub.PutPrivateData("oldCollection", key, value)
// after
// use a collection name present in collections_config.json
err := stub.PutPrivateData("collectionMarbles", key, value)
Defensive patterns

Strategy: validation

Validate before calling

func collectionDefined(cfgPkg *peer.CollectionConfigPackage, name string) bool {
  for _, c := range cfgPkg.GetConfig() {
    if sc := c.GetStaticCollectionConfig(); sc != nil && sc.Name == name { return true }
  }
  return false
}

Try / catch

if err != nil && strings.Contains(err.Error(), "no configuration for collection") {
  // re-check collection name vs collections_config.json
}

Prevention

When it happens

Trigger: computeDisseminationPlan calls getCollectionConfig for a collection name that has no matching StaticCollectionConfig entry in the namespace's CollectionConfigPackage.

Common situations: Data written under an older collection name that was renamed or removed in the latest collection config; typo in collection name in chaincode; reconciliation of private data spanning a config update that dropped the collection.

Related errors


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

Appendix: source

Thrown at gossip/privdata/distributor.go:213

			dPlan, err := d.disseminationPlanForMsg(colAP, colFilter, pvtDataMsg)
			if err != nil {
				return nil, errors.WithMessagef(err, "could not build private data dissemination plan for chaincode %s and collection %s", namespace, collectionName)
			}
			disseminationPlan = append(disseminationPlan, dPlan...)
		}
	}
	return disseminationPlan, nil
}

func (d *distributorImpl) getCollectionConfig(config *peer.CollectionConfigPackage, collection *rwset.CollectionPvtReadWriteSet) (*peer.CollectionConfig, error) {
	for _, c := range config.Config {
		if staticConfig := c.GetStaticCollectionConfig(); staticConfig != nil {
			if staticConfig.Name == collection.CollectionName {
				return c, nil
			}
		}
	}
	return nil, errors.New(fmt.Sprint("no configuration for collection", collection.CollectionName, "found"))
}

func (d *distributorImpl) disseminationPlanForMsg(colAP privdata.CollectionAccessPolicy, colFilter privdata.Filter, pvtDataMsg *protoext.SignedGossipMessage) ([]*dissemination, error) {
	var disseminationPlan []*dissemination

	routingFilter, err := d.gossipAdapter.PeerFilter(gossipCommon.ChannelID(d.chainID), func(signature api.PeerSignature) bool {
		return colFilter(protoutil.SignedData{
			Data:      signature.Message,
			Signature: signature.Signature,
			Identity:  signature.PeerIdentity,
		})
	})
	if err != nil {
		d.logger.Error("Failed to retrieve peer routing filter for channel", d.chainID, ":", err)
		return nil, err
	}

	m := pvtDataMsg.GetPrivateData().Payload

View on GitHub (pinned to 2736b63f8f)