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

  1. Pass exactly the string "Admins" or "Members" (matching constants policy.Admins / policy.Members) to the channelless check API
  2. Use channel-aware CheckPolicy (with channelID) if you need channel policies like Writers/Readers — channelless local checks only support Admins/Members
  3. 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

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


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/570fd5f3613b3b62. Report an issue: GitHub.