hyperledger/fabric · error

collection-name: %s -- cannot unmarshal identity bytes into

Error message

collection-name: %s -- cannot unmarshal identity bytes into MSPRole

What it means

During private data collection config validation, each principal in a collection's member-orgs policy is unmarshaled as an MSPRole protobuf. This error is thrown when proto.Unmarshal fails on the principal bytes, meaning the bytes embedded in the MSPPrincipal are not a valid MSPRole message. It almost always indicates a malformed or hand-crafted collection signature policy.

Source

Thrown at core/chaincode/lifecycle/scc.go:867

	}

	msps, err := mspMgr.GetMSPs()
	if err != nil {
		return errors.Wrapf(err, "could not get MSPs")
	}

	// make sure that the orgs listed are actually part of the channel
	// check all principals in the signature policy
	for _, principal := range coll.MemberOrgsPolicy.GetSignaturePolicy().Identities {
		var orgID string
		// the member org policy only supports certain principal types
		switch principal.PrincipalClassification {

		case mspprotos.MSPPrincipal_ROLE:
			msprole := &mspprotos.MSPRole{}
			err := proto.Unmarshal(principal.Principal, msprole)
			if err != nil {
				return errors.Wrapf(err, "collection-name: %s -- cannot unmarshal identity bytes into MSPRole", coll.GetName())
			}
			orgID = msprole.MspIdentifier
			// the msp map is indexed using msp IDs - this behavior is implementation specific, making the following check a bit of a hack
			_, ok := msps[orgID]
			if !ok {
				return errors.Errorf("collection-name: %s -- collection member '%s' is not part of the channel", coll.GetName(), orgID)
			}

		case mspprotos.MSPPrincipal_ORGANIZATION_UNIT:
			mspou := &mspprotos.OrganizationUnit{}
			err := proto.Unmarshal(principal.Principal, mspou)
			if err != nil {
				return errors.Wrapf(err, "collection-name: %s -- cannot unmarshal identity bytes into OrganizationUnit", coll.GetName())
			}
			orgID = mspou.MspIdentifier
			// the msp map is indexed using msp IDs - this behavior is implementation specific, making the following check a bit of a hack
			_, ok := msps[orgID]
			if !ok {

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Regenerate the collection config with standard tooling (e.g. peer collection JSON -> proto from fabric-samples tooling) instead of hand-crafting the signature policy.
  2. Verify the MSPPrincipal.Principal bytes are actually a marshaled MSPRole with a MspIdentifier set.
  3. Confirm the principal classification field matches the payload type (ROLE classification with MSPRole bytes).
  4. Check the protobuf library version used to serialize the policy matches fabric's expectations.

Example fix

// before (hand-crafted, mismatched payload)
principal := &mspprotos.MSPPrincipal{PrincipalClassification: mspprotos.MSPPrincipal_ROLE, Principal: sigPolicyBytes}
// after
role, _ := proto.Marshal(&mspprotos.MSPRole{MspIdentifier: "Org1MSP", Role: mspprotos.MSPRole_MEMBER})
principal := &mspprotos.MSPPrincipal{PrincipalClassification: mspprotos.MSPPrincipal_ROLE, Principal: role}
Defensive patterns

Strategy: validation

Validate before calling

for _, p := range policy.Identities {
  if p.PrincipalClassification == mspprotos.MSPPrincipal_ROLE {
    var r mspprotos.MSPRole
    if err := proto.Unmarshal(p.Principal, &r); err != nil {
      return fmt.Errorf("invalid ROLE principal for collection %s: %w", coll.Name, err)
    }
  }
}

Type guard

func isRolePrincipal(p *mspprotos.MSPPrincipal) (*mspprotos.MSPRole, bool) {
  if p == nil || p.PrincipalClassification != mspprotos.MSPPrincipal_ROLE {
    return nil, false
  }
  r := &mspprotos.MSPRole{}
  if proto.Unmarshal(p.Principal, r) != nil {
    return nil, false
  }
  return r, true
}

Try / catch

_, err := proto.Unmarshal(principal.Principal, msprole)
if err != nil {
  return fmt.Errorf("collection %s: malformed ROLE principal: %w", collName, err)
}

Prevention

When it happens

Trigger: Submitting a chaincode define/approve with a collection config whose member_orgs_policy contains an MSPPrincipal with classification ROLE whose Principal bytes do not decode into an MSPRole (wrong protobuf, corrupted bytes, manually assembled policy).

Common situations: Hand-written collection configs generated by custom tooling instead of configtxgen-style helpers; bytes from a different principal type placed under a ROLE classification; protobuf version mismatch when serializing the policy.

Understand the failure class

Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.

Related errors


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