hyperledger/fabric · error

MemberOrgsPolicy of %s is nil

Error message

MemberOrgsPolicy of %s is nil

What it means

To derive which organizations can endorse for a collection, discovery reads the collection's MemberOrgsPolicy. If a static collection in the chaincode's collection config has a nil MemberOrgsPolicy, discovery cannot compute the principal set and fails with this error naming the collection.

Source

Thrown at discovery/endorsement/collection.go:29

	"github.com/hyperledger/fabric/common/policies"
	"github.com/hyperledger/fabric/gossip/api"
	"github.com/pkg/errors"
)

func principalsFromCollectionConfig(ccp *peer.CollectionConfigPackage) (principalSetsByCollectionName, error) {
	principalSetsByCollections := make(principalSetsByCollectionName)
	if ccp == nil {
		return principalSetsByCollections, nil
	}
	for _, colConfig := range ccp.Config {
		staticCol := colConfig.GetStaticCollectionConfig()
		if staticCol == nil {
			// Right now we only support static collections, so if we got something else
			// we should refuse to process further
			return nil, errors.Errorf("expected a static collection but got %v instead", colConfig)
		}
		if staticCol.MemberOrgsPolicy == nil {
			return nil, errors.Errorf("MemberOrgsPolicy of %s is nil", staticCol.Name)
		}
		pol := staticCol.MemberOrgsPolicy.GetSignaturePolicy()
		if pol == nil {
			return nil, errors.Errorf("policy of %s is nil", staticCol.Name)
		}
		var principals policies.PrincipalSet
		// We now extract all principals from the policy
		for _, principal := range pol.Identities {
			principals = append(principals, principal)
		}
		principalSetsByCollections[staticCol.Name] = principals
	}
	return principalSetsByCollections, nil
}

type principalSetsByCollectionName map[string]policies.PrincipalSet

// toIdentityFilter converts this principalSetsByCollectionName mapping to a filter

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Redeploy the collection config ensuring every collection specifies a member orgs policy (e.g. OR('Org1MSP.peer','Org2MSP.peer'))
  2. Validate the collection JSON before approval (verify memberOrgsPolicy present)
  3. Re-approve/re-commit the chaincode definition with a corrected collections file

Example fix

// before collection JSON
{"name":"coll1","requiredPeerCount":1,"maxPeerCount":2}

// after
{"name":"coll1","memberOrgsPolicy":{"signaturePolicy":{"identities":[{"role":{"name":"peer","mspId":"Org1MSP"}}]}},"requiredPeerCount":1,"maxPeerCount":2}
Defensive patterns

Strategy: validation

Validate before calling

for _, col := range collConfig.Config {
    sc := col.GetStaticCollectionConfig()
    if sc != nil && sc.MemberOrgsPolicy == nil {
        return fmt.Errorf("collection %s missing memberOrgsPolicy", sc.Name)
    }
}

Type guard

func hasMemberOrgsPolicy(sc *pb.StaticCollectionConfig) bool {
    return sc != nil && sc.GetMemberOrgsPolicy() != nil
}

Try / catch

_, err := coll.PrincipalsFromCollectionConfig(ccp)
if err != nil {
    if strings.Contains(err.Error(), "MemberOrgsPolicy") {
        col := strings.Split(err.Error(), "MemberOrgsPolicy of ")[1]
        return nil, fmt.Errorf("fix memberOrgsPolicy for collection %s and re-approve", strings.TrimSuffix(col, " is nil"))
    }
    return nil, err
}

Prevention

When it happens

Trigger: A deployed collection definition with MemberOrgsPolicy unset (empty/incorrectly serialized collection config) reaching principalsFromCollectionConfig via loadMetadataAndFilters during a PeersForEndorsement request.

Common situations: Programmatically constructed collection JSON missing the member_orgs_policy field; config corrupted through tooling that dropped the policy; mismatches between collection config format versions.

Related errors


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