{"record":{"id":"5fa23aec60fbac27","repo":"hyperledger/fabric","slug":"unrecognized-type-expected-a-number-got-s","errorCode":null,"errorMessage":"unrecognized type, expected a number, got %s","messagePattern":"unrecognized type, expected a number, got (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/policydsl/policyparser.go","lineNumber":151,"sourceCode":"\t/* get the first argument, we expect it to be the context */\n\tvar ctx *context\n\tswitch v := args[0].(type) {\n\tcase *context:\n\t\tctx = v\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"unrecognized type, expected the context, got %s\", reflect.TypeOf(args[0]))\n\t}\n\n\t/* get the second argument, we expect an integer telling us\n\t   how many of the remaining we expect to have*/\n\tvar t int\n\tswitch arg := args[1].(type) {\n\tcase float64:\n\t\tt = int(arg)\n\tcase int:\n\t\tt = arg\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"unrecognized type, expected a number, got %s\", reflect.TypeOf(args[1]))\n\t}\n\n\t/* get the n in the t out of n */\n\tn := len(args) - 2\n\n\t/* sanity check - t should be positive, permit equal to n+1, but disallow over n+1 */\n\tif t < 0 || t > n+1 {\n\t\treturn nil, fmt.Errorf(\"invalid t-out-of-n predicate, t %d, n %d\", t, n)\n\t}\n\n\tpolicies := make([]*cb.SignaturePolicy, 0)\n\n\t/* handle the rest of the arguments */\n\tfor _, principal := range args[2:] {\n\t\tswitch t := principal.(type) {\n\t\t/* if it's a string, we expect it to be formed as\n\t\t   <MSP_ID> . <ROLE>, where MSP_ID is the MSP identifier\n\t\t   and ROLE is either a member, an admin, a client, a peer or an orderer*/","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/common/policydsl/policyparser.go#L133-L169","documentation":"secondPass expects its second argument to be the threshold t, and only accepts float64 or int (float64 because the expression evaluator treats numbers as float64). Any other type in the threshold slot fails with 'unrecognized type, expected a number, got <T>'.","triggerScenarios":"An intermediate string where the second outof argument is not numeric — e.g. 'outof(ID, \"2\", ...)' produced by a gate whose threshold was a quoted string, or calling secondPass directly with a string/int64 threshold.","commonSituations":"User policies like \"OutOf('2', 'Org1.member')\" where the threshold was quoted and survives as a string into secondPass; programmatic gate construction passing int64/uint64 thresholds; locale/templating code turning numbers into strings.","solutions":["Write the threshold unquoted and numeric in the policy: OutOf(2, ...) not OutOf('2', ...).","Convert the threshold to int (or float64) before any direct secondPass call: secondPass(ctx, int(t), ...).","Reject/normalize non-numeric thresholds in code that assembles policies from user config.","Check upstream gate functions (and/or) — they inject len(args) or 1, so a custom wrapper must do the same."],"exampleFix":"// before\npolicydsl.FromString(\"OutOf('2', 'Org1.member', 'Org2.member')\")\n// after\npolicydsl.FromString(\"OutOf(2, 'Org1.member', 'Org2.member')\")","handlingStrategy":"type-guard","validationCode":"switch args[1].(type) {\ncase int, float64:\n\t// ok\ndefault:\n\treturn fmt.Errorf(\"threshold must be numeric, got %T\", args[1])\n}","typeGuard":"func isNumericThreshold(v any) bool {\n\tswitch v.(type) {\n\tcase int, float64:\n\t\treturn true\n\t}\n\treturn false\n}","tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"expected a number\") {\n\treturn nil, fmt.Errorf(\"policy threshold must be unquoted and numeric: %w\", err)\n}","preventionTips":["Write thresholds unquoted: OutOf(2, ...), never OutOf('2', ...).","Convert int64/uint64/float32 thresholds to int before gate construction.","Validate user-supplied threshold config parses as an integer at load time."],"tags":["policydsl","hyperledger-fabric","type-error","threshold"],"backgroundTag":"unexpected-argument-type","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}