Tencent/WeKnora · error
between operator value must be a slice with two elements: %v
Error message
between operator value must be a slice with two elements: %v
What it means
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.
Source
Thrown at internal/application/repository/retriever/milvus/filter.go:192
paramName := c.convertParamName(cond.Field, counter)
return &convertResult{
exprStr: fmt.Sprintf("%s %s {%s}", condField, strings.ToLower(cond.Operator), paramName),
params: map[string]any{paramName: cond.Value},
}, nil
}
func (c *filter) convertBetweenCondition(
cond *universalFilterCondition,
counter *int,
) (*convertResult, error) {
condField := cond.Field
if condField == "" || cond.Value == nil {
return nil, fmt.Errorf("milvus filter condition is nil")
}
value := reflect.ValueOf(cond.Value)
if value.Kind() != reflect.Slice || value.Len() != 2 {
return nil, fmt.Errorf("between operator value must be a slice with two elements: %v", cond.Value)
}
paramBase := c.convertParamName(cond.Field, counter)
paramName1 := fmt.Sprintf("%s_%d", paramBase, 0)
paramName2 := fmt.Sprintf("%s_%d", paramBase, 1)
return &convertResult{
exprStr: fmt.Sprintf("%s >= {%s} and %s <= {%s}", condField, paramName1, condField, paramName2),
params: map[string]any{
paramName1: value.Index(0).Interface(),
paramName2: value.Index(1).Interface(),
},
}, nil
}
func formatValue(value any) string {
switch v := value.(type) {
case string:
return fmt.Sprintf("\"%s\"", escapeDoubleQuotes(v))View on GitHub (pinned to 988cbb0330)
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
Example fix
// before
cond := &UniversalFilterCondition{Field: "age", Operator: "BETWEEN", Value: []int{18}}
// after
cond := &UniversalFilterCondition{Field: "age", Operator: "BETWEEN", Value: []int{18, 65}} Defensive patterns
Strategy: validation
Validate before calling
rv := reflect.ValueOf(cond.Value)
if rv.Kind() != reflect.Slice || rv.Len() != 2 {
return fmt.Errorf("BETWEEN requires exactly [min, max]")
} Type guard
func isTwoElementSlice(c *UniversalFilterCondition) bool {
if c.Value == nil { return false }
v := reflect.ValueOf(c.Value)
return v.Kind() == reflect.Slice && v.Len() == 2
} Try / catch
res, err := f.Convert(ctx, cond)
if err != nil {
if strings.Contains(err.Error(), "two elements") {
return nil, fmt.Errorf("BETWEEN value must be [min,max]: %w", err)
}
return nil, err
} Prevention
- Always pass exactly two bounds
- Use min/max variables to make the pair explicit
- Reject open-ended ranges at construction; use >=/<= operators instead
When it happens
Trigger: BETWEEN with a scalar value, a one-element slice, or a three-plus-element slice.
Common situations: Passing [lower] intending an open-ended range; passing [lower, upper, step]; mixing up BETWEEN with IN semantics.
Related errors
- in operator value must be a slice with at least one value: %
- milvus filter condition is nil
- unsupported comparison operator: %s
- invalid logical condition value type
- empty logical condition
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/1a4c16740bae65ab.
Report an issue: GitHub.