{"record":{"id":"bde1f46023b2a042","repo":"hyperledger/fabric","slug":"could-not-unmarshal-combinedprincipal-from-princip","errorCode":null,"errorMessage":"could not unmarshal CombinedPrincipal from principal","messagePattern":"could not unmarshal CombinedPrincipal from principal","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"msp/mspimpl.go","lineNumber":460,"sourceCode":"\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\n// collectPrincipals collects principals from combined principals into a single MSPPrincipal slice.\nfunc collectPrincipals(principal *m.MSPPrincipal, mspVersion MSPVersion) ([]*m.MSPPrincipal, error) {\n\tswitch principal.PrincipalClassification {\n\tcase m.MSPPrincipal_COMBINED:\n\t\t// Combined principals are not supported in MSP v1.0 or v1.1\n\t\tif mspVersion <= MSPv1_1 {\n\t\t\treturn nil, errors.Errorf(\"invalid principal type %d\", int32(principal.PrincipalClassification))\n\t\t}\n\t\t// Principal is a combination of multiple principals.\n\t\tprincipals := &m.CombinedPrincipal{}\n\t\terr := proto.Unmarshal(principal.Principal, principals)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"could not unmarshal CombinedPrincipal from principal\")\n\t\t}\n\t\t// Return an error if there are no principals in the combined principal.\n\t\tif len(principals.Principals) == 0 {\n\t\t\treturn nil, errors.New(\"No principals in CombinedPrincipal\")\n\t\t}\n\t\t// Recursively call msp.collectPrincipals for all combined principals.\n\t\t// There is no limit for the levels of nesting for the combined principals.\n\t\tvar principalsSlice []*m.MSPPrincipal\n\t\tfor _, cp := range principals.Principals {\n\t\t\tinternalSlice, err := collectPrincipals(cp, mspVersion)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tprincipalsSlice = append(principalsSlice, internalSlice...)\n\t\t}\n\t\t// All the combined principals have been collected into principalsSlice\n\t\treturn principalsSlice, nil\n\tdefault:","sourceCodeStart":442,"sourceCodeEnd":478,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/msp/mspimpl.go#L442-L478","documentation":"collectPrincipals wraps proto.Unmarshal failures when deserializing the principal.Principal payload into a CombinedPrincipal message, producing 'could not unmarshal CombinedPrincipal from principal: <cause>'. The principal was classified as COMBINED, but its opaque bytes are not a valid protobuf-encoded CombinedPrincipal.","triggerScenarios":"Calling SatisfiesPrincipal/collectPrincipals with an MSPPrincipal whose PrincipalClassification is COMBINED but whose Principal bytes were built incorrectly — hand-marshaled bytes, bytes from a different message type (e.g. an MSPRole or OrganizationUnit), corrupted in transit, or an empty payload that fails unmarshal in the caller's proto version.","commonSituations":"Fabric SDK or tooling marshaling the wrong proto message into the COMBINED principal; policy files edited/re-serialized by external tools; byte corruption or truncation during policy transmission; mixing protobuf implementations with incompatible wire bytes.","solutions":["Inspect the wrapped cause; regenerate the principal via proto.Marshal on a properly populated &m.CombinedPrincipal{Principals: [...]}","Verify the SDK/API used to build the policy constructs CombinedPrincipal, not another MSPPrincipal payload type","Re-export/recreate the policy from the original toolchain instead of hand-editing serialized bytes","Validate round-trip: proto.Unmarshal the payload before submitting the policy"],"exampleFix":"// before\nprincipal := &m.MSPPrincipal{PrincipalClassification: m.MSPPrincipal_COMBINED, Principal: roleBytes} // wrong payload\n// after\ninner := &m.MSPPrincipal{PrincipalClassification: m.MSPPrincipal_ROLE,\n    Principal: proto.MarshalTextString(...) /* properly marshaled MSPPrincipal */}\ncpBytes, _ := proto.Marshal(&m.CombinedPrincipal{Principals: []*m.MSPPrincipal{inner, inner2}})\nprincipal := &m.MSPPrincipal{PrincipalClassification: m.MSPPrincipal_COMBINED, Principal: cpBytes}","handlingStrategy":"validation","validationCode":"cp := &m.CombinedPrincipal{}\nif err := proto.Unmarshal(principal.Principal, cp); err != nil {\n    return fmt.Errorf(\"principal payload is not a valid CombinedPrincipal: %w\", err)\n}\n// proceed with the MSP call only after this passes","typeGuard":"func isValidCombinedPrincipalPayload(b []byte) bool {\n    cp := &m.CombinedPrincipal{}\n    return proto.Unmarshal(b, cp) == nil\n}","tryCatchPattern":"ok, err := msp.SatisfiesPrincipal(id, principal)\nif err != nil {\n    if strings.Contains(err.Error(), \"could not unmarshal CombinedPrincipal\") {\n        log.Errorf(\"malformed COMBINED principal payload: %v\", err)\n    }\n    return err\n}","preventionTips":["Build COMBINED principals only via proto.Marshal(&m.CombinedPrincipal{Principals: [...]}) — never hand-pack bytes","Confirm the inner Principal bytes are marshaled MSPPrincipal messages, not MSPRole/OrganizationUnit payloads","Re-generate policies from the original SDK/toolchain instead of editing serialized policy blobs","Round-trip test: Unmarshal the serialized principal before embedding it in a policy"],"tags":["protobuf","unmarshal","combined-principal","msp","hyperledger-fabric"],"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"}