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
- Pass a plain numeric literal as the offset: PREV(PRICE, 1)
- If building programmatically, use CEPLiteral.of(new BigDecimal(1)) so the type name is DECIMAL
- 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
- Use unquoted numeric literals for PREV/LAST offsets
- When constructing CEPLiteral programmatically, use CEPLiteral.of(new BigDecimal(n))
- Keep offsets small and non-negative; 0 means current event
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
- the first argument of the PREV operation should be a field…
- CEP operation is not recognized
- RexNode not supported
- the comparator is not supported
- the function in Measures is not recognized.
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)