{"record":{"id":"5d6f75d8123603b5","repo":"go-playground/validator","slug":"bad-param-number-for-required-unless-s","errorCode":null,"errorMessage":"Bad param number for required_unless %s","messagePattern":"Bad param number for required_unless (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"baked_in.go","lineNumber":2163,"sourceCode":"\tparams := parseOneOfParam2(fl.Param())\n\tif len(params)%2 != 0 {\n\t\tpanic(fmt.Sprintf(\"Bad param number for excluded_if %s\", fl.FieldName()))\n\t}\n\n\tfor i := 0; i < len(params); i += 2 {\n\t\tif !requireCheckFieldValue(fl, params[i], params[i+1], false) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn !hasValue(fl)\n}\n\n// requiredUnless is the validation function\n// The field under validation must be present and not empty only unless all the other specified fields are equal to the value following with the specified field.\nfunc requiredUnless(fl FieldLevel) bool {\n\tparams := parseOneOfParam2(fl.Param())\n\tif len(params)%2 != 0 {\n\t\tpanic(fmt.Sprintf(\"Bad param number for required_unless %s\", fl.FieldName()))\n\t}\n\n\tfor i := 0; i < len(params); i += 2 {\n\t\tif requireCheckFieldValue(fl, params[i], params[i+1], false) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn hasValue(fl)\n}\n\n// skipUnless is the validation function\n// The field under validation must be present and not empty only unless all the other specified fields are equal to the value following with the specified field.\nfunc skipUnless(fl FieldLevel) bool {\n\tparams := parseOneOfParam2(fl.Param())\n\tif len(params)%2 != 0 {\n\t\tpanic(fmt.Sprintf(\"Bad param number for skip_unless %s\", fl.FieldName()))\n\t}\n\tfor i := 0; i < len(params); i += 2 {","sourceCodeStart":2145,"sourceCodeEnd":2181,"githubUrl":"https://github.com/go-playground/validator/blob/facf128d2eecf42bd4ff447adc961aa21bb64aed/baked_in.go#L2145-L2181","documentation":"required_unless makes the field required unless every listed field equals its value. Parameters must form complete field,value pairs; an odd count panics at baked_in.go:2163 with 'Bad param number for required_unless'.","triggerScenarios":"Tag like `required_unless=Role` or `required_unless=Role,admin,Level` — odd comma-split param count, often from a missing value or an unescaped comma in a value.","commonSituations":"Tag copied from required_unless docs of another library that takes bare field names; missing value after a field name; dynamic tag builders appending an odd token.","solutions":["Write full pairs: `required_unless=Role,admin`.","Verify the param splits into an even number after comma parsing.","Use required_without if you only need field-presence semantics.","Cover the tag with a unit test."],"exampleFix":"// before\nRole string\nSSN  string `validate:\"required_unless=Role\"`\n\n// after\nRole string\nSSN  string `validate:\"required_unless=Role,admin\"`","handlingStrategy":"validation","validationCode":"func checkRequiredUnlessTag(tagValue string) error {\n    parts := strings.Split(tagValue, \",\")\n    if len(parts)%2 != 0 {\n        return fmt.Errorf(\"required_unless needs field,value pairs; got %d params in %q\", len(parts), tagValue)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"func safeValidate(v *Validate, s interface{}) (err error) {\n    defer func() {\n        if r := recover(); r != nil {\n            err = fmt.Errorf(\"validator panic (check required_unless params): %v\", r)\n        }\n    }()\n    return v.Struct(s)\n}","preventionTips":["Write required_unless=Field,value pairs, not bare field lists","Don't confuse with required_without (which takes bare field names)","Escape commas inside values","Add tag smoke tests to CI"],"tags":["go","validator","panic","struct-tags","required-unless"],"backgroundTag":"invalid-validator-tag-params","analyzedSha":"facf128d2eecf42bd4ff447adc961aa21bb64aed","analyzedAt":"2026-09-02T10:19:04.986Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T16:17:10.729Z"}