Tencent/WeKnora · error

unsupported comparison operator: %s

Error message

unsupported comparison operator: %s

What it means

convertComparisonCondition looks up cond.Operator in the comparisonOperators map and returns 'unsupported comparison operator: %s' when the operator has no Milvus expression translation. Only operators present in that map (e.g. ==, !=, >, <, in) are supported; anything else cannot be rendered into a Milvus boolean expression.

Source

Thrown at internal/application/repository/retriever/milvus/filter.go:86

type filter struct{}

func (c *filter) Convert(cond *universalFilterCondition) (*convertResult, error) {
	var counter int
	return c.convertCondition(cond, &counter)
}

func (c *filter) convertComparisonCondition(
	cond *universalFilterCondition,
	counter *int,
) (*convertResult, error) {
	condField := cond.Field
	if condField == "" || cond.Value == nil {
		return nil, fmt.Errorf("milvus filter condition is nil")
	}
	operator, ok := comparisonOperators[cond.Operator]
	if !ok {
		return nil, fmt.Errorf("unsupported comparison operator: %s", cond.Operator)
	}

	paramName := c.convertParamName(cond.Field, counter)
	return &convertResult{
		exprStr: fmt.Sprintf("%s %s {%s}", condField, operator, paramName),
		params:  map[string]any{paramName: cond.Value},
	}, nil
}

func (c *filter) convertLogicalCondition(
	cond *universalFilterCondition,
	counter *int,
) (*convertResult, error) {
	if cond.Value == nil {
		return nil, fmt.Errorf("milvus filter condition is nil")
	}
	conds, ok := cond.Value.([]*universalFilterCondition)
	if !ok {

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Check the operator value in the error and replace it with one supported by comparisonOperators (==, !=, >, >=, <, <=, in, etc.).
  2. If the semantic operator is needed, add a mapping entry translating it to a Milvus-supported expression (e.g. use text_match or range expressions).
  3. Normalize operator casing/aliases at the filter-parse boundary before conversion.
  4. Validate the operator against a whitelist in the caller before building conditions.

Example fix

// before
newCond("title", "contains", title) // 'contains' unsupported
// after
newCond("title", "in", []string{"prefix..."}) // or extend comparisonOperators with a text_match mapping
Defensive patterns

Strategy: validation

Validate before calling

var supportedOps = map[string]bool{"==":true,"!=":true,">":true,">=":true,"<":true,"<=":true,"in":true}
if !supportedOps[cond.Operator] { return fmt.Errorf("operator %q not supported for milvus", cond.Operator) }

Prevention

When it happens

Trigger: Passing an operator like 'contains', 'like', '~=', 'startsWith', or a database-specific SQL operator that the map does not cover, often when translating a filter DSL written for another vector store (e.g. Pinecone/Postgres) directly to Milvus.

Common situations: Cross-store filter DSLs reused between retrievers; frontend sending free-text operators; new operator added to the universal filter type without extending comparisonOperators; case mismatch ('IN' vs 'in').

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/4d93dc58b5289947. Report an issue: GitHub.