hyperledger/fabric · error
MSP Principal role [%s] not recognized
Error message
MSP Principal role [%s] not recognized
What it means
localMSPPrincipalGetter.Get only recognizes the literal role strings 'Admins' and 'Members' (the exported constants). Any other role string hits the default branch and returns this error. It means the caller passed a role name that the local principal getter cannot map to an MSPPrincipal.
Source
Thrown at core/policy/principal.go:76
return nil, errors.Wrap(err, "marshalling failed")
}
return &protomsp.MSPPrincipal{
PrincipalClassification: protomsp.MSPPrincipal_ROLE,
Principal: principalBytes,
}, nil
case Members:
principalBytes, err := proto.Marshal(&protomsp.MSPRole{Role: protomsp.MSPRole_MEMBER, MspIdentifier: mspid})
if err != nil {
return nil, errors.Wrap(err, "marshalling failed")
}
return &protomsp.MSPPrincipal{
PrincipalClassification: protomsp.MSPPrincipal_ROLE,
Principal: principalBytes,
}, nil
default:
return nil, errors.Errorf("MSP Principal role [%s] not recognized", role)
}
}
View on GitHub (pinned to 2736b63f8f)
Solutions
- Pass exactly the string "Admins" or "Members" (matching constants policy.Admins / policy.Members) to the channelless check API
- Use channel-aware CheckPolicy (with channelID) if you need channel policies like Writers/Readers — channelless local checks only support Admins/Members
- Check for case/typo errors: the match is exact and case-sensitive
Example fix
// before
err := checker.CheckPolicyNoChannelBySignedData("/Channel/Application/Admins", signedData)
// after
err := checker.CheckPolicyNoChannelBySignedData("Admins", signedData) // or policy.Admins Defensive patterns
Strategy: validation
Validate before calling
var validLocalRoles = map[string]bool{"Admins": true, "Members": true}
func validateLocalRole(role string) error {
if !validLocalRoles[role] {
return fmt.Errorf("role %q not supported for channelless local check; use Admins or Members", role)
}
return nil
} Type guard
func isSupportedLocalRole(role string) bool {
return role == "Admins" || role == "Members"
} Try / catch
if err := checker.CheckPolicyNoChannelBySignedData(policyName, signedData); err != nil {
if strings.Contains(err.Error(), "not recognized") {
return fmt.Errorf("invalid local policy name %q: use Admins or Members", policyName)
}
return err
} Prevention
- Reference the exported constants policy.Admins / policy.Members instead of raw strings
- Never pass channel policy paths like /Channel/Application/Admins to channelless APIs
- Match case exactly: 'admins' is rejected
- Use the channel-based CheckPolicy for Writers/Readers/channel policies
When it happens
Trigger: Calling CheckPolicyNoChannelBySignedData (policy.go:209 principalGetter.Get(policyName)) with a policyName other than exactly "Admins" or "Members" — e.g. passing a channel policy name like "Writers", "Readers", a path like "/Channel/Application/Admins", or a misspelled/locally defined policy name into the channelless local-MSP check.
Common situations: Mixing up channel policy names with the channelless local policy names ('Admins'/'Members'); older Fabric code or custom chaincode passing '/Channel/Application/...' paths; case mismatch like 'admins' or 'ADMIN'; config using custom local policy names not supported by the getter.
Related errors
- Failed getting local MSP principal during channelless check
- failed verifying that the signed data identity satisfies loc
- No principals in CombinedPrincipal
- could not unmarshal MSPRole from principal
- the identity is a member of a different MSP (expected %s, go
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/570fd5f3613b3b62.
Report an issue: GitHub.