hyperledger/fabric · error

unexpected collection type

Error message

unexpected collection type

What it means

The collection access policy factory only understands CollectionConfig_StaticCollectionConfig. When the oneof in peer.CollectionConfig carries any other type (or none), the factory rejects it with 'unexpected collection type'. Static collections are the only supported private-collection kind in this code path.

Source

Thrown at gossip/privdata/distributor.go:114

type CollectionAccessPolicy interface {
	privdata.CollectionAccessPolicy
}

// policyAccessFactory the implementation of CollectionAccessFactory
type policyAccessFactory struct {
	IdentityDeserializerFactory
}

func (p *policyAccessFactory) AccessPolicy(config *peer.CollectionConfig, chainID string) (privdata.CollectionAccessPolicy, error) {
	colAP := &privdata.SimpleCollection{}
	switch cconf := config.Payload.(type) {
	case *peer.CollectionConfig_StaticCollectionConfig:
		err := colAP.Setup(cconf.StaticCollectionConfig, p.GetIdentityDeserializer(chainID))
		if err != nil {
			return nil, errors.WithMessagef(err, "error setting up collection  %#v", cconf.StaticCollectionConfig.Name)
		}
	default:
		return nil, errors.New("unexpected collection type")
	}
	return colAP, nil
}

// NewCollectionAccessFactory
func NewCollectionAccessFactory(factory IdentityDeserializerFactory) CollectionAccessFactory {
	return &policyAccessFactory{
		IdentityDeserializerFactory: factory,
	}
}

// NewDistributor a constructor for private data distributor capable to send
// private read write sets for underlying collection
func NewDistributor(chainID string, gossip gossipAdapter, factory CollectionAccessFactory,
	metrics *metrics.PrivdataMetrics, pushAckTimeout time.Duration,
) PvtDataDistributor {
	return &distributorImpl{
		chainID:                 chainID,

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Fix collections_config.json so each entry uses static_collection_config.
  2. Regenerate the collection config with official Fabric tooling for your version.
  3. Ensure the collection config proto's oneof is explicitly set before calling AccessPolicy.
  4. Upgrade peers/tooling so Fabric versions agree on the collection-config schema.

Example fix

// before: malformed collection config (missing static config)
{
  "name": "mycollection"
}

// after: proper static collection config
{
  "static_collection_config": {
    "name": "mycollection",
    "member_orgs_policy": {"signature_policy": {...}},
    "required_peer_count": 3,
    "maximum_peer_count": 3,
    "block_to_live": 0
  }
}
Defensive patterns

Strategy: validation

Validate before calling

for _, c := range collectionConfigs {
    if c.GetStaticCollectionConfig() == nil {
        return errors.New("only static collection configs are supported")
    }
}

Type guard

func isStaticCollectionConfig(cc *peer.CollectionConfig) bool {
    return cc != nil && cc.GetStaticCollectionConfig() != nil
}

Try / catch

colAP, err := factory.AccessPolicy(collectionConfigPackage, chainID)
if err != nil {
    if strings.Contains(err.Error(), "unexpected collection type") {
        return errors.New("collection config must use static_collection_config; regenerate collections_config.json")
    }
    return err
}

Prevention

When it happens

Trigger: A collection config package passed to AccessPolicy contains a CollectionConfig whose type field is unset or not StaticCollectionConfig — e.g. a malformed or hand-built collections_config.json, or a proto produced by newer tooling with types this Fabric version doesn't know.

Common situations: Hand-edited or generated collections_config.json missing the static_collection_config wrapper; proto field set with the wrong oneof variant; Fabric version mismatch where a config produced by newer tooling is loaded by an older peer.

Related errors


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