hyperledger/fabric · error
unexpected type %s
Error message
unexpected type %s
What it means
In outof(), the first argument is the threshold t of a t-out-of-n policy and must be a float64, int, or string. Any other type (bool, struct, nil, etc.) cannot be rendered into the intermediate policy string, so the library fails with 'unexpected type <T>'.
Source
Thrown at common/policydsl/policyparser.go:65
// This will be evaluated by second/third passes to convert to a proto policy
func outof(args ...any) (any, error) {
var toret strings.Builder
toret.WriteString("outof(")
if len(args) < 2 {
return nil, fmt.Errorf("expected at least two arguments to NOutOf. Given %d", len(args))
}
arg0 := args[0]
// govaluate treats all numbers as float64 only. But and/or may pass int/string. Allowing int/string for flexibility of caller
if n, ok := arg0.(float64); ok {
toret.WriteString(strconv.Itoa(int(n)))
} else if n, ok := arg0.(int); ok {
toret.WriteString(strconv.Itoa(n))
} else if n, ok := arg0.(string); ok {
toret.WriteString(n)
} else {
return nil, fmt.Errorf("unexpected type %s", reflect.TypeOf(arg0))
}
for _, arg := range args[1:] {
toret.WriteString(", ")
switch t := arg.(type) {
case string:
if regex.MatchString(t) {
toret.WriteString("'" + t + "'")
} else {
toret.WriteString(t)
}
default:
return nil, fmt.Errorf("unexpected type %s", reflect.TypeOf(arg))
}
}
return toret.String() + ")", nilView on GitHub (pinned to 2736b63f8f)
Solutions
- Pass the threshold as int, float64, or a numeric string: OutOf(2, ...) or OutOf("2", ...).
- Convert other numeric types before the call, e.g. OutOf(int(n64), principals...).
- Check argument order — the threshold must be args[0], principals after it.
- If generated by code, add a type assertion/switch on the threshold value before invoking outof.
Example fix
// before policydsl.OutOf(uint(2), "Org1.member") // uint is unsupported // after policydsl.OutOf(int(2), "Org1.member")
Defensive patterns
Strategy: type-guard
Validate before calling
switch t.(type) {
case int, float64, string:
// ok
default:
return fmt.Errorf("threshold must be int/float64/string, got %T", t)
} Type guard
func isValidThreshold(v any) bool {
switch v.(type) {
case int, float64, string:
return true
}
return false
} Try / catch
_, err := policydsl.OutOf(threshold, principals...)
if err != nil && strings.Contains(err.Error(), "unexpected type") {
return nil, fmt.Errorf("threshold %v (%T) is not numeric/string", threshold, threshold)
} Prevention
- Pass thresholds as int (or float64/string); convert int64/uint/float32 first.
- Keep the threshold as the first argument, principals after.
- Never pass protos, bools, or nil in the threshold slot.
- Add a typed Gate builder struct that only accepts int thresholds.
When it happens
Trigger: Calling policydsl.OutOf(true, ...), OutOf(nil, ...), or OutOf(someStruct, ...) directly, or building gates programmatically where the threshold slot receives a non-numeric, non-string value.
Common situations: Passing an unsigned/int64/int32 threshold from config code without converting to int; accidentally swapping arguments so a principal struct lands in the threshold slot; using a *cb.SignaturePolicy where a number is expected.
Related errors
- unrecognized type, expected a number, got %s
- unrecognized type, expected the context, got %s
- invalid t-out-of-n predicate, t %d, n %d
- expected at least two arguments to NOutOf. Given %d
- at least 3 arguments expected, got %d
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/6eec6514ab4fe5a4.
Report an issue: GitHub.