{"record":{"id":"a193d905131ed44d","repo":"hyperledger/fabric","slug":"expected-at-least-two-arguments-to-noutof-given","errorCode":null,"errorMessage":"expected at least two arguments to NOutOf. Given %d","messagePattern":"expected at least two arguments to NOutOf\\. Given (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/policydsl/policyparser.go","lineNumber":53,"sourceCode":"\tRoleOrderer = \"orderer\"\n)\n\nvar (\n\tregex = regexp.MustCompile(\n\t\tfmt.Sprintf(\"^([[:alnum:].-]+)([.])(%s|%s|%s|%s|%s)$\",\n\t\t\tRoleAdmin, RoleMember, RoleClient, RolePeer, RoleOrderer),\n\t)\n\tregexErr = regexp.MustCompile(\"^No parameter '([^']+)' found[.]$\")\n)\n\n// a stub function - it returns the same string as it's passed.\n// This will be evaluated by second/third passes to convert to a proto policy\nfunc outof(args ...any) (any, error) {\n\tvar toret strings.Builder\n\ttoret.WriteString(\"outof(\")\n\n\tif len(args) < 2 {\n\t\treturn nil, fmt.Errorf(\"expected at least two arguments to NOutOf. Given %d\", len(args))\n\t}\n\n\targ0 := args[0]\n\t// govaluate treats all numbers as float64 only. But and/or may pass int/string. Allowing int/string for flexibility of caller\n\tif n, ok := arg0.(float64); ok {\n\t\ttoret.WriteString(strconv.Itoa(int(n)))\n\t} else if n, ok := arg0.(int); ok {\n\t\ttoret.WriteString(strconv.Itoa(n))\n\t} else if n, ok := arg0.(string); ok {\n\t\ttoret.WriteString(n)\n\t} else {\n\t\treturn nil, fmt.Errorf(\"unexpected type %s\", reflect.TypeOf(arg0))\n\t}\n\n\tfor _, arg := range args[1:] {\n\t\ttoret.WriteString(\", \")\n\n\t\tswitch t := arg.(type) {","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/common/policydsl/policyparser.go#L35-L71","documentation":"policydsl.outof() builds the intermediate 'outof(t, ...)' string used to convert a policy DSL expression into a SignaturePolicy. It requires at least two arguments: the threshold t and at least one principal/policy. Fewer than two arguments means a t-out-of-n policy with no subjects, which is meaningless, so the library rejects it.","triggerScenarios":"Calling OutOf(t) with zero or one additional subject (e.g. OutOf(1) or OutOf()), or a policy string like 'OutOf(1)' evaluated via FromString so that and/or/outof receives fewer than 2 args.","commonSituations":"Hand-written policy strings missing subjects ('OutOf(2)') after an editor stripped a trailing principal; programmatic builders that append principals conditionally and end up empty (e.g. empty channel/application org list); typos like 'OutOf(2,)' that the expr parser drops.","solutions":["Ensure OutOf is called with at least one subject: OutOf(t, principal1[, principal2...]).","Check the policy string passed to FromString and add the missing principal(s), e.g. 'OutOf(1, \"Org1.member\")'.","If principals are built dynamically, validate that the list is non-empty before calling OutOf; fall back to a default policy or return a config error.","If you only need a single-subject policy, use SignedBy directly instead of OutOf."],"exampleFix":"// before\npolicy, err := policydsl.FromString(\"OutOf(1)\")\n// after\npolicy, err := policydsl.FromString(\"OutOf(1, 'Org1.member')\")","handlingStrategy":"validation","validationCode":"func validateGateArgs(t any, principals ...string) error {\n\tif len(principals) < 1 {\n\t\treturn fmt.Errorf(\"OutOf requires at least one principal\")\n\t}\n\treturn nil\n}","typeGuard":"func hasMinArgs(args []any, n int) bool { return len(args) >= n }","tryCatchPattern":"policy, err := policydsl.FromString(spec)\nif err != nil {\n\tif strings.Contains(err.Error(), \"expected at least two arguments to NOutOf\") {\n\t\treturn nil, fmt.Errorf(\"policy %q has a gate with no subjects: %w\", spec, err)\n\t}\n\treturn nil, err\n}","preventionTips":["Always pass at least one principal after the threshold in OutOf/And/Or gates.","Validate dynamically built principal lists are non-empty before composing the policy string.","Quote principals in policy strings: OutOf(1, 'Org1.member').","Add unit tests for every policy string shipped in config."],"tags":["policydsl","hyperledger-fabric","argument-count","signature-policy"],"backgroundTag":"invalid-function-arity","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"}