{"record":{"id":"5077d99815d615cb","repo":"Tencent/WeKnora","slug":"in-operator-value-must-be-a-slice-with-at-least-on","errorCode":null,"errorMessage":"in operator value must be a slice with at least one value: %v","messagePattern":"in operator value must be a slice with at least one value: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/application/repository/retriever/milvus/filter.go","lineNumber":171,"sourceCode":"\tcase operatorBetween:\n\t\treturn c.convertBetweenCondition(cond, counter)\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"unsupported operator: %v\", cond.Operator)\n\t}\n}\n\nfunc (c *filter) convertInCondition(\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\ts := reflect.ValueOf(cond.Value)\n\tif s.Kind() != reflect.Slice || s.Len() <= 0 {\n\t\treturn nil, fmt.Errorf(\"in operator value must be a slice with at least one value: %v\", cond.Value)\n\t}\n\n\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","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/application/repository/retriever/milvus/filter.go#L153-L189","documentation":"convertInCondition requires the IN/NOT_IN Value to be a slice containing at least one element. It uses reflection to check Value's kind and length and returns this error when Value is not a slice or is an empty slice, including Value's content in the message.","triggerScenarios":"IN condition with Value as a scalar (e.g. a single string), a map, or an empty slice like []string{}.","commonSituations":"Passing a single value intending 'equals'; JSON arrays that ended up empty after filtering; Go interface{} wrapping that loses the slice type.","solutions":["Ensure Value is a non-empty slice (e.g. []string{...} or []int{...})","If a single value is intended, use the EQUAL operator instead of IN","Guard the length before building the condition"],"exampleFix":"// before\ncond := &UniversalFilterCondition{Field: \"tag\", Operator: \"IN\", Value: \"red\"}\n// after\ncond := &UniversalFilterCondition{Field: \"tag\", Operator: \"IN\", Value: []string{\"red\"}}","handlingStrategy":"validation","validationCode":"rv := reflect.ValueOf(cond.Value)\nif rv.Kind() != reflect.Slice || rv.Len() == 0 {\n  return fmt.Errorf(\"IN requires a non-empty slice\")\n}","typeGuard":"func isInSlice(c *UniversalFilterCondition) bool {\n  if c.Value == nil { return false }\n  v := reflect.ValueOf(c.Value)\n  return v.Kind() == reflect.Slice && v.Len() > 0\n}","tryCatchPattern":"res, err := f.Convert(ctx, cond)\nif err != nil {\n  if strings.Contains(err.Error(), \"must be a slice\") {\n    return nil, fmt.Errorf(\"IN value must be a non-empty slice: %w\", err)\n  }\n  return nil, err\n}","preventionTips":["Wrap single values in a one-element slice for IN","Check slice length before constructing the condition","Prefer typed builders ([]string, []int) over interface{} literals"],"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"}