hyperledger/fabric · error
invalid principal type %d
Error message
invalid principal type %d
What it means
collectPrincipals rejects MSPPrincipal values classified as COMBINED when the MSP version is v1.0 or v1.1, with 'invalid principal type %d' reporting the numeric classification. Combined principals (MSPv1_3+) allow nesting multiple principals into an AND-group, and older MSP versions explicitly do not understand them.
Source
Thrown at msp/mspimpl.go:454
if err != nil {
return err
}
for _, principal := range principals {
err = msp.internalSatisfiesPrincipalInternalFunc(id, principal)
if err != nil {
return err
}
}
return nil
}
// collectPrincipals collects principals from combined principals into a single MSPPrincipal slice.
func collectPrincipals(principal *m.MSPPrincipal, mspVersion MSPVersion) ([]*m.MSPPrincipal, error) {
switch principal.PrincipalClassification {
case m.MSPPrincipal_COMBINED:
// Combined principals are not supported in MSP v1.0 or v1.1
if mspVersion <= MSPv1_1 {
return nil, errors.Errorf("invalid principal type %d", int32(principal.PrincipalClassification))
}
// Principal is a combination of multiple principals.
principals := &m.CombinedPrincipal{}
err := proto.Unmarshal(principal.Principal, principals)
if err != nil {
return nil, errors.Wrap(err, "could not unmarshal CombinedPrincipal from principal")
}
// Return an error if there are no principals in the combined principal.
if len(principals.Principals) == 0 {
return nil, errors.New("No principals in CombinedPrincipal")
}
// Recursively call msp.collectPrincipals for all combined principals.
// There is no limit for the levels of nesting for the combined principals.
var principalsSlice []*m.MSPPrincipal
for _, cp := range principals.Principals {
internalSlice, err := collectPrincipals(cp, mspVersion)
if err != nil {
return nil, errView on GitHub (pinned to 2736b63f8f)
Solutions
- Enable the V1_3 (or later) channel capability and update the MSP version so combined principals are accepted
- Rewrite the policy to avoid MSPPrincipal_COMBINED: use implicit meta policies or express the logic as a signature policy tree instead
- If rejection is intended, nothing to fix — the error is the guard against using v1.3 features on an older MSP
Example fix
// before (channel config)
Capabilities:
Channel: {V1_1: true} # combined principals rejected
// after
Capabilities:
Channel: {V1_3: true} # MSPv1_3, combined principals supported Defensive patterns
Strategy: validation
Validate before calling
func combinedPrincipalsSupported(version msp.MSPVersion) bool {
return version > msp.MSPv1_1 // e.g. MSPv1_3
}
// before evaluating a policy, check principal.PrincipalClassification != m.MSPPrincipal_COMBINED || combinedPrincipalsSupported(mspVersion) Type guard
func isCombinedPrincipal(p *m.MSPPrincipal) bool {
return p != nil && p.PrincipalClassification == m.MSPPrincipal_COMBINED
} Try / catch
principals, err := msp.SatisfiesPrincipal(id, principal)
if err != nil {
if strings.Contains(err.Error(), "invalid principal type") {
// COMBINED principal on an MSP <= v1.1; upgrade MSP version or rewrite policy
}
return err
} Prevention
- Keep policy features aligned with channel capabilities: combined principals require V1_3+ capability / MSPv1_3
- Prefer implicit meta policies or signature policy trees when targeting older MSP versions
- Audit all channel/application configs for MSP version before deploying v1.3-era policies
- Test policy evaluation against the exact MSP version configured in production
When it happens
Trigger: Calling SatisfiesPrincipal (or any policy evaluation path that calls collectPrincipals) against an MSPPrincipal with PrincipalClassification=MSPPrincipal_COMBINED while the MSP's version is MSPv1_0 or MSPv1_1. Also produced directly by unit tests TestCollectEmptyCombinedPrincipal and TestCollectPrincipalContainingEmptyCombinedPrincipal which assert this rejection.
Common situations: Channel/application config still at MSP v1.1 (set via configtx Channel capabilities / MSPVersion) while an endorsement or ACL policy was authored with a combined principal; upgrading policies without upgrading channel capabilities to V1_3 or later.
Related errors
- Empty policy element
- missing policy at path: %s
- ConfigPolicy not found at policy path: %s
- unexpected missing policy %s for item %s
- policy for %s not satisfied
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/910937864a485864.
Report an issue: GitHub.