hyperledger/fabric · error

error parsing principal %s

Error message

error parsing principal %s

What it means

When a subject in secondPass is a string, it must match the principal regex ^<MSP_ID>.<ROLE>$ with ROLE one of member|admin|client|peer|orderer. A string that doesn't match (wrong separator, unknown role, spaces, nested-gate text landing in the wrong pass) fails with 'error parsing principal <s>'.

Source

Thrown at common/policydsl/policyparser.go:174

	/* sanity check - t should be positive, permit equal to n+1, but disallow over n+1 */
	if t < 0 || t > n+1 {
		return nil, fmt.Errorf("invalid t-out-of-n predicate, t %d, n %d", t, n)
	}

	policies := make([]*cb.SignaturePolicy, 0)

	/* handle the rest of the arguments */
	for _, principal := range args[2:] {
		switch t := principal.(type) {
		/* if it's a string, we expect it to be formed as
		   <MSP_ID> . <ROLE>, where MSP_ID is the MSP identifier
		   and ROLE is either a member, an admin, a client, a peer or an orderer*/
		case string:
			/* split the string */
			subm := regex.FindAllStringSubmatch(t, -1)
			if subm == nil || len(subm) != 1 || len(subm[0]) != 4 {
				return nil, fmt.Errorf("error parsing principal %s", t)
			}

			/* get the right role */
			var r mb.MSPRole_MSPRoleType

			switch subm[0][3] {
			case RoleMember:
				r = mb.MSPRole_MEMBER
			case RoleAdmin:
				r = mb.MSPRole_ADMIN
			case RoleClient:
				r = mb.MSPRole_CLIENT
			case RolePeer:
				r = mb.MSPRole_PEER
			case RoleOrderer:
				r = mb.MSPRole_ORDERER
			default:
				return nil, fmt.Errorf("error parsing role %s", t)

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Format every principal as '<MSP_ID>.<ROLE>' with a literal dot and lowercase role: 'Org1.member', 'Org1MSP.admin'.
  2. Use only the supported roles: member, admin, client, peer, orderer.
  3. Trim whitespace and verify the MSP ID contains only alphanumerics, dots, and dashes.
  4. If you need a nested gate, wrap it in its gate call (e.g. And('Org1.member','Org2.member')) rather than passing it as a bare string subject.

Example fix

// before
policydsl.FromString("OutOf(1, 'Org1/peer', 'Org2.member')")
// after
policydsl.FromString("OutOf(1, 'Org1.peer', 'Org2.member')")
Defensive patterns

Strategy: validation

Validate before calling

var principalRe = regexp.MustCompile(`^([[:alnum:].-]+)\.(member|admin|client|peer|orderer)$`)
func validPrincipal(p string) bool { return principalRe.MatchString(p) }
// check each principal before composing the policy string

Type guard

func isPrincipal(s string) bool {
	return principalRe.MatchString(s)
}

Try / catch

if err != nil && strings.Contains(err.Error(), "error parsing principal") {
	return nil, fmt.Errorf("principals must look like 'Org1.member' with role in {member,admin,client,peer,orderer}: %w", err)
}

Prevention

When it happens

Trigger: Principals like 'Org1 Member', 'Org1/peer', 'Org1.owner' (unknown role), or an empty MSP ID ('.member'); also gate keywords ('And', 'or') reaching secondPass as subjects because of malformed nesting in the policy string.

Common situations: Typos in role names ('peers', 'Member' capitalized is actually matched since regex is case-sensitive lowercase — 'Member' fails); using ':' or '/' instead of '.' between MSP ID and role; copying peer CLI -s flag values that aren't principal strings; MSP IDs with characters outside [[:alnum:].-].

Related errors


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