hyperledger/fabric · error

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

Error message

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

What it means

For ORGANIZATION_UNIT-class principals in a collection member orgs policy, the principal bytes are unmarshaled into an OrganizationUnit protobuf. This error is thrown when that unmarshal fails, meaning the bytes are not a valid OrganizationUnit message. It indicates a malformed collection signature policy.

Source

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

		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 {
				return errors.Errorf("collection-name: %s -- collection member '%s' is not part of the channel", coll.GetName(), orgID)
			}

		case mspprotos.MSPPrincipal_IDENTITY:
			if _, err := mspMgr.DeserializeIdentity(principal.Principal); err != nil {
				return errors.Errorf("collection-name: %s -- contains an identity that is not part of the channel", coll.GetName())
			}

		default:
			return errors.Errorf("collection-name: %s -- principal type %v is not supported", coll.GetName(), principal.PrincipalClassification)
		}
	}
	return nil

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Marshal a proper mspprotos.OrganizationUnit (MspIdentifier, OrganizationalUnitIdentifier, CertifiersIdentifier) and use those bytes.
  2. Prefer ROLE principals, which are simpler and the common pattern for collections.
  3. Validate the generated policy by deserializing it before submitting the chaincode definition.
  4. Regenerate the collection config with standard tooling.

Example fix

// before
principal := &mspprotos.MSPPrincipal{PrincipalClassification: mspprotos.MSPPrincipal_ORGANIZATION_UNIT, Principal: []byte("Org1/unit1")}
// after
ou, _ := proto.Marshal(&mspprotos.OrganizationUnit{MspIdentifier: "Org1MSP", OrganizationalUnitIdentifier: "unit1"})
principal := &mspprotos.MSPPrincipal{PrincipalClassification: mspprotos.MSPPrincipal_ORGANIZATION_UNIT, Principal: ou}
Defensive patterns

Strategy: validation

Validate before calling

if p.PrincipalClassification == mspprotos.MSPPrincipal_ORGANIZATION_UNIT {
  var ou mspprotos.OrganizationUnit
  if err := proto.Unmarshal(p.Principal, &ou); err != nil {
    return fmt.Errorf("invalid ORGANIZATION_UNIT principal: %w", err)
  }
}

Type guard

func isOUPrincipal(p *mspprotos.MSPPrincipal) (*mspprotos.OrganizationUnit, bool) {
  if p == nil || p.PrincipalClassification != mspprotos.MSPPrincipal_ORGANIZATION_UNIT {
    return nil, false
  }
  ou := &mspprotos.OrganizationUnit{}
  if proto.Unmarshal(p.Principal, ou) != nil {
    return nil, false
  }
  return ou, true
}

Try / catch

defer func() {
  if r := recover(); r != nil { /* handle malformed policy construction */ }
}()
// or on submission:
if err := submit(); err != nil {
  if strings.Contains(err.Error(), "cannot unmarshal identity bytes into OrganizationUnit") {
    // rebuild policy with marshaled OrganizationUnit bytes
  }
}

Prevention

When it happens

Trigger: A collection config member_orgs_policy principal with classification ORGANIZATION_UNIT whose Principal bytes are not a marshaled OrganizationUnit protobuf.

Common situations: Custom policy-building code stuffing raw strings or wrong message types into the Principal field; copying policy bytes between different classification types; corrupted serialized policies.

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/762d147e753c0b93. Report an issue: GitHub.