apache/beam · error · IllegalStateException

the second argument of the prev operation should be a…

Error message

the second argument of the prev operation should be a decimal. Provided: ${class}

What it means

The offset argument of PREV must be a DECIMAL literal: it says how many events back to look. The NFA's prev() checks opr2.getTypeName() == Schema.TypeName.DECIMAL and throws IllegalStateException for any other literal type (string, int-as-other-type, etc.), because only a numeric decimal offset can index into the event history.

Solutions

  1. Pass a plain numeric literal as the offset: PREV(PRICE, 1)
  2. If building programmatically, use CEPLiteral.of(new BigDecimal(1)) so the type name is DECIMAL
  3. Note the offset 0 is allowed and returns the current event

Example fix

// before
PREV(PRICE, '1')
// after
PREV(PRICE, 1)
Defensive patterns

Strategy: validation

Validate before calling

if (prevOffset.getTypeName() != Schema.TypeName.DECIMAL) {
  throw new IllegalArgumentException("PREV offset must be a decimal literal");
}

Type guard

boolean isDecimalLiteral(CEPOperation op) {
  return op instanceof CEPLiteral && ((CEPLiteral) op).getTypeName() == Schema.TypeName.DECIMAL;
}

Try / catch

try {
  runCepQuery(pattern);
} catch (IllegalStateException e) {
  if (e.getMessage().startsWith("the second argument of the prev operation")) {
    // correct the offset literal type
  } else throw e;
}

Prevention

When it happens

Trigger: PREV(field, x) where x's CEPLiteral type is not DECIMAL (e.g. a VARCHAR or INTEGER literal), or calling prev() programmatically with a non-DECIMAL CEPLiteral.

Common situations: Writing PREV(PRICE, '1') with a string offset; relying on a dialect where integer literals are a different type than DECIMAL; constructing CEPLiteral.of with the wrong type.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

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

      }
    }

    /* below are function implementations */

    // represents the PREV operation
    private CEPLiteral prev(
        CEPOperation opr1,
        CEPLiteral opr2,
        EventPointer curPointer,
        Event curEvent,
        Event inputEvent) {
      if (opr1.getClass() != CEPFieldRef.class) {
        throw new IllegalStateException(
            "the first argument of the PREV operation should be a field reference. Provided: "
                + opr1.getClass().toString());
      }
      if (opr2.getTypeName() != Schema.TypeName.DECIMAL) {
        throw new IllegalStateException(
            "the second argument of the prev operation should be a decimal. Provided: "
                + opr2.getClass().toString());
      }
      // if the second argument is 0, return the current event
      if (opr2.getDecimal().intValue() == 0) {
        return inputEvent.toCEPLiteral((CEPFieldRef) opr1);
      }
      // for the starting event, return null
      if (curEvent == null) {
        return null;
      }
      CEPFieldRef fieldRef = (CEPFieldRef) opr1;
      String alpha = fieldRef.getAlpha(); // the patternVar
      int lastNumber = opr2.getDecimal().intValue();
      EventPointer iterPointer = curPointer.copy();

      while (curEvent != null && iterPointer.getPatternVar().equals(alpha) && lastNumber > 0) {
        iterPointer = curEvent.getPrevPointer(iterPointer);

View on GitHub (pinned to 12126d8942)