hyperledger/fabric · error
invalid policy string '%s'
Error message
invalid policy string '%s'
What it means
FromString (common/policydsl/policyparser.go:290) compiles and runs the policy DSL through the expr expression evaluator, whose gate functions (and/or/outof) build an intermediate string like 'outof(...)'. After the first evaluation the result must be a string; if expr returns a non-string value (e.g. a boolean from a comparison-only expression, or nothing at all), the parser gives up with 'invalid policy string'. It signals that the input is not a well-formed policy expression at all, even though it may be syntactically valid to expr.
Source
Thrown at common/policydsl/policyparser.go:290
if err != nil {
return nil, err
}
intermediateRes, err := expr.Run(intermediate, env)
if err != nil {
// attempt to produce a meaningful error
if regexErr.MatchString(err.Error()) {
sm := regexErr.FindStringSubmatch(err.Error())
if len(sm) == 2 {
return nil, fmt.Errorf("unrecognized token '%s' in policy string", sm[1])
}
}
return nil, err
}
resStr, ok := intermediateRes.(string)
if !ok {
return nil, fmt.Errorf("invalid policy string '%s'", policy)
}
// we still need two passes. The first pass just adds an extra
// argument ID to each of the outof calls. This is
// required because govaluate has no means of giving context
// to user-implemented functions other than via arguments.
// We need this argument because we need a global place where
// we put the identities that the policy requires
env = map[string]interface{}{
"outof": firstPass,
}
exp, err := expr.Compile(resStr, expr.Env(env))
if err != nil {
return nil, err
}
res, err := expr.Run(exp, env)
if err != nil {
// attempt to produce a meaningful errorView on GitHub (pinned to 2736b63f8f)
Solutions
- Wrap the policy in a valid gate call: every policy must have And/Or/OutOf at its root, e.g. OutOf(1, 'Org1.member', 'Org2.member')
- Ensure the policy string is non-empty and contains no bare expressions that evaluate to booleans/numbers
- Quote every principal argument ('Org1.member') so expr treats it as a string literal for the gate functions
- Test the string with policydsl.FromString before embedding it in channel/chaincode policy configuration
Example fix
// before
FromString("Org1.member") // no gate -> result is not a string
// after
FromString("OutOf(1, 'Org1.member', 'Org1.admin')") Defensive patterns
Strategy: validation
Validate before calling
func validatePolicyString(policy string) error {
trimmed := strings.TrimSpace(policy)
if trimmed == "" {
return fmt.Errorf("policy string is empty")
}
gateRe := regexp.MustCompile(`(?i)^(and|or|outof)\s*\(`)
if !gateRe.MatchString(trimmed) {
return fmt.Errorf("policy %q must start with an And/Or/OutOf call", policy)
}
return nil
} Try / catch
_, err := policydsl.FromString(policy)
if err != nil && strings.Contains(err.Error(), "invalid policy string") {
return fmt.Errorf("policy %q is not a gate expression; wrap principals in And/Or/OutOf: %w", policy, err)
} Prevention
- Always root the policy in an And/Or/OutOf gate call - a bare principal is invalid
- Reject empty/whitespace policy strings before calling FromString
- Do not embed boolean/numeric expressions in policy strings
- Add a config-load-time check that runs FromString on every policy
When it happens
Trigger: Calling policydsl.FromString with an expression that evaluates to a non-string, e.g. FromString("Org1.member") (a boolean/identifier, not a gate call), FromString("OutOf()"), an empty string, or an expression like '1 == 1' that expr evaluates to true rather than a gate string.
Common situations: Passing an empty or whitespace-only policy string from config; passing just an MSP principal without any And/Or/OutOf gate; copy-paste errors where the outer gate call was dropped; programmatic callers that build policy strings and concatenate incorrectly.
Related errors
- unrecognized type, expected a principal or a policy, got %s
- unrecognized token '%s' in policy string
- error marshalling msp role: %s
- error adding policies to orderer group
- invalid principal type %d
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/f131045a0b3a46f4.
Report an issue: GitHub.