{"record":{"id":"b52eff10caf30269","repo":"hyperledger/fabric","slug":"collection-name-s-cannot-unmarshal-identity-b","errorCode":null,"errorMessage":"collection-name: %s -- cannot unmarshal identity bytes into MSPRole","messagePattern":"collection-name: (.+?) -- cannot unmarshal identity bytes into MSPRole","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/chaincode/lifecycle/scc.go","lineNumber":867,"sourceCode":"\t}\n\n\tmsps, err := mspMgr.GetMSPs()\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"could not get MSPs\")\n\t}\n\n\t// make sure that the orgs listed are actually part of the channel\n\t// check all principals in the signature policy\n\tfor _, principal := range coll.MemberOrgsPolicy.GetSignaturePolicy().Identities {\n\t\tvar orgID string\n\t\t// the member org policy only supports certain principal types\n\t\tswitch principal.PrincipalClassification {\n\n\t\tcase mspprotos.MSPPrincipal_ROLE:\n\t\t\tmsprole := &mspprotos.MSPRole{}\n\t\t\terr := proto.Unmarshal(principal.Principal, msprole)\n\t\t\tif err != nil {\n\t\t\t\treturn errors.Wrapf(err, \"collection-name: %s -- cannot unmarshal identity bytes into MSPRole\", coll.GetName())\n\t\t\t}\n\t\t\torgID = msprole.MspIdentifier\n\t\t\t// the msp map is indexed using msp IDs - this behavior is implementation specific, making the following check a bit of a hack\n\t\t\t_, ok := msps[orgID]\n\t\t\tif !ok {\n\t\t\t\treturn errors.Errorf(\"collection-name: %s -- collection member '%s' is not part of the channel\", coll.GetName(), orgID)\n\t\t\t}\n\n\t\tcase mspprotos.MSPPrincipal_ORGANIZATION_UNIT:\n\t\t\tmspou := &mspprotos.OrganizationUnit{}\n\t\t\terr := proto.Unmarshal(principal.Principal, mspou)\n\t\t\tif err != nil {\n\t\t\t\treturn errors.Wrapf(err, \"collection-name: %s -- cannot unmarshal identity bytes into OrganizationUnit\", coll.GetName())\n\t\t\t}\n\t\t\torgID = mspou.MspIdentifier\n\t\t\t// the msp map is indexed using msp IDs - this behavior is implementation specific, making the following check a bit of a hack\n\t\t\t_, ok := msps[orgID]\n\t\t\tif !ok {","sourceCodeStart":849,"sourceCodeEnd":885,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/chaincode/lifecycle/scc.go#L849-L885","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Regenerate the collection config with standard tooling (e.g. peer collection JSON -> proto from fabric-samples tooling) instead of hand-crafting the signature policy.","Verify the MSPPrincipal.Principal bytes are actually a marshaled MSPRole with a MspIdentifier set.","Confirm the principal classification field matches the payload type (ROLE classification with MSPRole bytes).","Check the protobuf library version used to serialize the policy matches fabric's expectations."],"exampleFix":"// before (hand-crafted, mismatched payload)\nprincipal := &mspprotos.MSPPrincipal{PrincipalClassification: mspprotos.MSPPrincipal_ROLE, Principal: sigPolicyBytes}\n// after\nrole, _ := proto.Marshal(&mspprotos.MSPRole{MspIdentifier: \"Org1MSP\", Role: mspprotos.MSPRole_MEMBER})\nprincipal := &mspprotos.MSPPrincipal{PrincipalClassification: mspprotos.MSPPrincipal_ROLE, Principal: role}","handlingStrategy":"validation","validationCode":"for _, p := range policy.Identities {\n  if p.PrincipalClassification == mspprotos.MSPPrincipal_ROLE {\n    var r mspprotos.MSPRole\n    if err := proto.Unmarshal(p.Principal, &r); err != nil {\n      return fmt.Errorf(\"invalid ROLE principal for collection %s: %w\", coll.Name, err)\n    }\n  }\n}","typeGuard":"func isRolePrincipal(p *mspprotos.MSPPrincipal) (*mspprotos.MSPRole, bool) {\n  if p == nil || p.PrincipalClassification != mspprotos.MSPPrincipal_ROLE {\n    return nil, false\n  }\n  r := &mspprotos.MSPRole{}\n  if proto.Unmarshal(p.Principal, r) != nil {\n    return nil, false\n  }\n  return r, true\n}","tryCatchPattern":"_, err := proto.Unmarshal(principal.Principal, msprole)\nif err != nil {\n  return fmt.Errorf(\"collection %s: malformed ROLE principal: %w\", collName, err)\n}","preventionTips":["Generate collection configs with standard fabric tooling, never by hand-assembling protobuf bytes.","Keep principal classification and payload type in sync.","Deserialize-validate the policy before submitting the chaincode definition.","Pin protobuf serialization library versions."],"tags":["fabric","private-data","protobuf","collection-config"],"backgroundTag":"protobuf-unmarshal-failed","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}