apache/beam · error · IllegalStateException

the comparator is not supported: ${comparator}

Error message

the comparator is not supported: ${comparator}

What it means

NFA.evalCondition compares left and right CEPLiteral values using the SQL comparator from the RexCall. The switch handles EQUAL, NOT_EQUAL, GREATER_THAN, GREATER_THAN_OR_EQUAL, LESS_THAN, LESS_THAN_OR_EQUAL; any other SqlOperator reaches default and throws IllegalStateException.

Source

Thrown at sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/impl/nfa/NFA.java:498

      }
      if (rightSideValue == null) {
        return true;
      }
      switch (comparator) {
        case EQUALS:
          return leftSideValue.compareTo(rightSideValue) == 0;
        case NOT_EQUALS:
          return leftSideValue.compareTo(rightSideValue) != 0;
        case GREATER_THAN:
          return leftSideValue.compareTo(rightSideValue) > 0;
        case GREATER_THAN_OR_EQUAL:
          return leftSideValue.compareTo(rightSideValue) >= 0;
        case LESS_THAN:
          return leftSideValue.compareTo(rightSideValue) < 0;
        case LESS_THAN_OR_EQUAL:
          return leftSideValue.compareTo(rightSideValue) <= 0;
        default:
          throw new IllegalStateException(
              "the comparator is not supported: " + comparator.toString());
      }
    }

    // evaluates the condition value (left) given an input event
    private CEPLiteral evalLeftSideCondition(CEPOperation inputOperation, Event inputEvent) {
      if (inputOperation instanceof CEPLiteral) {
        return (CEPLiteral) inputOperation;
      } else if (inputOperation.getClass() == CEPFieldRef.class) {
        return inputEvent.toCEPLiteral((CEPFieldRef) inputOperation);
      } else if (inputOperation.getClass() == CEPCall.class) {
        CEPCall call = (CEPCall) inputOperation;
        CEPOperator operator = call.getOperator();
        List<CEPOperation> operands = call.getOperands();
        switch (operator.getCepKind()) {
          case LAST:
            return last(
                operands.get(0), evalLeftSideCondition(operands.get(1), inputEvent), inputEvent);

View on GitHub (pinned to 12126d8942)

Solutions

  1. Rewrite the condition using only =, <>, <, <=, >, >= comparisons between field expressions and literals.
  2. Replace IS NULL with explicit handling, e.g. compare after coalescing, or filter nulls before MATCH_RECOGNIZE.
  3. Replace LIKE/IN with equality ranges or pre-computed boolean fields upstream.
  4. Extend the switch in NFA.evalCondition to map the missing SqlOperator.

Example fix

// before
DEFINE A AS A.status LIKE 'ERR%'
// after (upstream)
.apply(MapElements.into(strings).via(...status...)) // then DEFINE A AS A.isError = TRUE
Defensive patterns

Strategy: validation

Validate before calling

// Allow-list comparison operators in DEFINE conditions
Set<SqlOperator> allowed = Set.of(EQUAL, NOT_EQUALS, LESS_THAN, LESS_THAN_OR_EQUAL, GREATER_THAN, GREATER_THAN_OR_EQUAL);
if (!allowed.contains(op)) throw new IllegalArgumentException("Unsupported comparator in DEFINE: " + op);

Type guard

boolean isSimpleComparison(SqlOperator op) { return op instanceof SqlBinaryOperator && COMPARISON_OPS.contains(op.getName().toUpperCase()); }

Try / catch

try { return nfa.proceed(...); } catch (IllegalStateException e) { throw new QueryValidationException("Unsupported comparator in DEFINE clause", e); }

Prevention

When it happens

Trigger: A DEFINE condition whose comparison operator is not one of the six standard SQL comparison operators — e.g. IS DISTINCT FROM, IS NULL, LIKE, IN, or a custom operator reaching the comparator switch.

Common situations: Using IS NULL / LIKE / IN predicates inside MATCH_RECOGNIZE DEFINE clauses; Calcite rewriting comparisons into operator kinds the NFA does not enumerate.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/3ed8360744965225. Report an issue: GitHub.