{"record":{"id":"1a4c16740bae65ab","repo":"Tencent/WeKnora","slug":"between-operator-value-must-be-a-slice-with-two-el","errorCode":null,"errorMessage":"between operator value must be a slice with two elements: %v","messagePattern":"between operator value must be a slice with two elements: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/application/repository/retriever/milvus/filter.go","lineNumber":192,"sourceCode":"\tparamName := c.convertParamName(cond.Field, counter)\n\treturn &convertResult{\n\t\texprStr: fmt.Sprintf(\"%s %s {%s}\", condField, strings.ToLower(cond.Operator), paramName),\n\t\tparams:  map[string]any{paramName: cond.Value},\n\t}, nil\n}\n\nfunc (c *filter) convertBetweenCondition(\n\tcond *universalFilterCondition,\n\tcounter *int,\n) (*convertResult, error) {\n\tcondField := cond.Field\n\tif condField == \"\" || cond.Value == nil {\n\t\treturn nil, fmt.Errorf(\"milvus filter condition is nil\")\n\t}\n\n\tvalue := reflect.ValueOf(cond.Value)\n\tif value.Kind() != reflect.Slice || value.Len() != 2 {\n\t\treturn nil, fmt.Errorf(\"between operator value must be a slice with two elements: %v\", cond.Value)\n\t}\n\n\tparamBase := c.convertParamName(cond.Field, counter)\n\tparamName1 := fmt.Sprintf(\"%s_%d\", paramBase, 0)\n\tparamName2 := fmt.Sprintf(\"%s_%d\", paramBase, 1)\n\treturn &convertResult{\n\t\texprStr: fmt.Sprintf(\"%s >= {%s} and %s <= {%s}\", condField, paramName1, condField, paramName2),\n\t\tparams: map[string]any{\n\t\t\tparamName1: value.Index(0).Interface(),\n\t\t\tparamName2: value.Index(1).Interface(),\n\t\t},\n\t}, nil\n}\n\nfunc formatValue(value any) string {\n\tswitch v := value.(type) {\n\tcase string:\n\t\treturn fmt.Sprintf(\"\\\"%s\\\"\", escapeDoubleQuotes(v))","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/application/repository/retriever/milvus/filter.go#L174-L210","documentation":"convertBetweenCondition requires Value to be a slice of exactly two elements (lower and upper bound). It uses reflection and returns this error when Value is not a slice or its length != 2, embedding Value in the message.","triggerScenarios":"BETWEEN with a scalar value, a one-element slice, or a three-plus-element slice.","commonSituations":"Passing [lower] intending an open-ended range; passing [lower, upper, step]; mixing up BETWEEN with IN semantics.","solutions":["Always pass a two-element slice: [min, max]","Use GREATER_THAN_OR_EQUAL / LESS_THAN_OR_EQUAL pair for open-ended ranges","Check array construction so exactly two bounds are provided"],"exampleFix":"// before\ncond := &UniversalFilterCondition{Field: \"age\", Operator: \"BETWEEN\", Value: []int{18}}\n// after\ncond := &UniversalFilterCondition{Field: \"age\", Operator: \"BETWEEN\", Value: []int{18, 65}}","handlingStrategy":"validation","validationCode":"rv := reflect.ValueOf(cond.Value)\nif rv.Kind() != reflect.Slice || rv.Len() != 2 {\n  return fmt.Errorf(\"BETWEEN requires exactly [min, max]\")\n}","typeGuard":"func isTwoElementSlice(c *UniversalFilterCondition) bool {\n  if c.Value == nil { return false }\n  v := reflect.ValueOf(c.Value)\n  return v.Kind() == reflect.Slice && v.Len() == 2\n}","tryCatchPattern":"res, err := f.Convert(ctx, cond)\nif err != nil {\n  if strings.Contains(err.Error(), \"two elements\") {\n    return nil, fmt.Errorf(\"BETWEEN value must be [min,max]: %w\", err)\n  }\n  return nil, err\n}","preventionTips":["Always pass exactly two bounds","Use min/max variables to make the pair explicit","Reject open-ended ranges at construction; use >=/<= operators instead"],"tags":["milvus","filter","type-error"],"backgroundTag":"invalid-filter-value-type","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}