hyperledger/fabric · error
unrecognized type, expected a principal or a policy, got %s
Error message
unrecognized type, expected a principal or a policy, got %s
What it means
secondPass in common/policydsl/policyparser.go:224 rejects an argument to an OutOf/And/Or gate that is neither a principal string nor a nested *cb.SignaturePolicy. The internal expression pipeline should only ever produce strings (principals like 'Org1.member') or previously built SignaturePolicy values; any other type reaching this switch means the generated expression was malformed or a function returned an unexpected type.
Source
Thrown at common/policydsl/policyparser.go:224
/* create a SignaturePolicy that requires a signature from
the principal we've just built*/
dapolicy := SignedBy(int32(ctx.IDNum))
policies = append(policies, dapolicy)
/* increment the identity counter. Note that this is
suboptimal as we are not reusing identities. We
can deduplicate them easily and make this puppy
smaller. For now it's fine though */
// TODO: deduplicate principals
ctx.IDNum++
/* if we've already got a policy we're good, just append it */
case *cb.SignaturePolicy:
policies = append(policies, t)
default:
return nil, fmt.Errorf("unrecognized type, expected a principal or a policy, got %s", reflect.TypeOf(principal))
}
}
return NOutOf(int32(t), policies), nil
}
type context struct {
IDNum int
principals []*mb.MSPPrincipal
}
func newContext() *context {
return &context{IDNum: 0, principals: make([]*mb.MSPPrincipal, 0)}
}
// FromString takes a string representation of the policy,
// parses it and returns a SignaturePolicyEnvelope that
// implements that policy. The supported language is as follows:View on GitHub (pinned to 2736b63f8f)
Solutions
- Quote the argument so it parses as a principal string of the form '<MSP_ID>.<role>' where role is one of member|admin|client|peer|orderer, e.g. OutOf(1, 'Org1.member')
- Check for unbalanced or misplaced parentheses that shift arguments between nested gates
- Ensure every argument to And/Or/OutOf is either a quoted principal or a nested gate call, never a number or bare identifier
- Test the policy string through policydsl.FromString in a unit test before deploying it in channel or chaincode policy config
Example fix
// before
FromString("OutOf(1, Org1.member, 2)")
// after
FromString("OutOf(1, 'Org1.member', 'Org1.peer')") Defensive patterns
Strategy: validation
Validate before calling
var principalRe = regexp.MustCompile(`^[[:alnum:].-]+[.](member|admin|client|peer|orderer)$`)
func validatePolicyArgs(policy string) error {
if !strings.Contains(policy, "And(") && !strings.Contains(policy, "Or(") && !strings.Contains(policy, "OutOf(") &&
!strings.Contains(policy, "and(") && !strings.Contains(policy, "or(") && !strings.Contains(policy, "outof(") {
return fmt.Errorf("policy %q must be rooted in And/Or/OutOf", policy)
}
return nil
}
// plus: every non-gate argument must match principalRe Try / catch
_, err := policydsl.FromString(policy)
if err != nil && strings.Contains(err.Error(), "unrecognized type, expected a principal or a policy") {
return fmt.Errorf("policy %q has a non-principal argument in a gate: %w", policy, err)
} Prevention
- Quote every principal argument ('Org1.member') so it is passed as a string
- Only use member|admin|client|peer|orderer as the role suffix
- Keep every argument to And/Or/OutOf either a quoted principal or a nested gate call
- Unit-test all policy strings with FromString before committing them to config
When it happens
Trigger: Calling policydsl.FromString with an expression argument inside a gate that is not a quoted principal and not a gate call, e.g. FromString("OutOf(1, Org1.member, 42)") or a bare identifier - expr passes it through and the switch's default branch fires.
Common situations: Typos in policy strings in channel configtx.yaml or policy definitions in chaincode (e.g. missing quotes around an MSP identifier, unbalanced parentheses causing arguments to shift, or passing numeric/naked tokens where 'OrgMSP.peer' style principals are expected).
Related errors
- unrecognized token '%s' in policy string
- invalid policy string '%s'
- expected at least two arguments to NOutOf. Given %d
- at least 3 arguments expected, got %d
- error marshalling msp role: %s
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/f88eb5b6ce618131.
Report an issue: GitHub.