Skip to content

bug: DataFilter != comparator with multiple values doesn't work as NOT IN #3808

@uptownhr

Description

@uptownhr

Summary

The != comparator in DataFilter with multiple values exhibits unintuitive behavior that makes it practically unusable. Instead of implementing true "NOT IN" semantics (value must not match ALL items in array), it currently implements "not equal to ANY" (passes on first mismatch).

Current Behavior

When using comparator: "!=" with multiple values, the filter passes if the event value is different from ANY value in the array, which means it will pass for almost any input.

Example:

filters:
  data:
    - path: body.brandId
      type: string
      value: ["id1", "id2", "id3"]
      comparator: "!="

Event: {"brandId": "id1"}

  • Current result: PASSES ✓ (because "id1" != "id2" is true)
  • Expected result: FAILS ✗ (because "id1" IS in the array)

Expected Behavior

The != comparator should implement true "NOT IN" semantics:

  • PASS: if value does not match ANY item in the array (value NOT IN array)
  • FAIL: if value matches any item in the array (value IN array)

Root Cause

In pkg/sensors/dependencies/filter.go, the implementation exits early on the first mismatch:

// Lines ~361-399 (string type)
for _, value := range f.Value {
    // ... regex matching ...
    switch f.Comparator {
    case v1alpha1.NotEqualTo:
        if !match {
            matchResult = true  // First mismatch
        }
    }
    
    if matchResult {
        continue filterData  // Exits loop early - WRONG!
    }
}
return false  // Only reached if ALL values matched

The same issue exists for number types (lines ~306-359) and bool types (lines ~278-304).

Test Coverage Gap

The existing test suite in filter_data_test.go has no test cases for != comparator with multiple values - all != tests use single-value arrays.

Reproduction Test Cases

{
    name: "string filter NotEqualTo with multiple values - value IN array",
    args: args{
        data: []v1alpha1.DataFilter{
            {
                Path:       "k",
                Type:       v1alpha1.JSONTypeString,
                Value:      []string{"id1", "id2", "id3"},
                Comparator: "!=",
            },
        },
        operator: v1alpha1.EmptyLogicalOperator,
        event: &v1alpha1.Event{
            Data: []byte(`{"k": "id1"}`),
        },
    },
    expectedResult: false,  // Should FAIL
    expectErr:      false,
}

Running this test with current code: PASSES (bug)
Running with fixed code: FAILS (correct)

Impact

  • The != comparator is essentially broken for practical use with multiple values
  • Users expecting "NOT IN" behavior will get incorrect results
  • No workaround except using expr filters with explicit AND logic

Proposed Fix

Check ALL values before deciding:

for _, value := range f.Value {
    if match {
        matchFound = true
        break
    }
}

// For != comparator, pass only if NO match was found
if f.Comparator == v1alpha1.NotEqualTo {
    if !matchFound {
        continue filterData  // PASS
    } else {
        return false  // FAIL
    }
}

Environment

  • All versions affected (present in current master branch)
  • Affects string, number, and bool data types

I'll prepare a PR with the fix and comprehensive test coverage.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions