apache/beam · error · IllegalStateException
the first argument of the PREV operation should be a field…
Error message
the first argument of the PREV operation should be a field reference. Provided: ${class} What it means
The PREV operation in a MATCH_RECOGNIZE pattern must take a field reference as its first argument, because PREV looks up a column value of a previous event. The NFA's StateLocator receives some other CEPOperation subclass (e.g. a literal or arithmetic expression) and throws IllegalStateException, since there is no meaningful 'previous value' of a non-column expression.
Solutions
- Change the first PREV argument to a plain field reference, e.g. PREV(PRICE, 1)
- Verify the parsed AST (opr1.getClass()) is CEPFieldRef if constructing CEPOperation nodes programmatically
- Check Beam SQL CEP docs for the exact PREV signature: PREV(field, offset-decimal)
Example fix
// before DEFINE e AS PREV(1, 1) // after DEFINE e AS PREV(PRICE, 1)
Defensive patterns
Strategy: validation
Validate before calling
// validate PREV argument before building/running the query
if (!(prevFirstArg instanceof CEPFieldRef)) {
throw new IllegalArgumentException("PREV requires a field reference");
} Type guard
boolean isFieldRef(CEPOperation op) {
return op instanceof CEPFieldRef;
} Try / catch
try {
runCepQuery(pattern);
} catch (IllegalStateException e) {
if (e.getMessage().startsWith("the first argument of the PREV operation")) {
// rewrite the pattern to use a plain field reference
} else throw e;
} Prevention
- Always write PREV(<column>, <numeric literal>) — never constants or expressions as the first argument
- Add a query lint in your tooling that rejects PREV/LAST with non-column first args
- Consult the Beam CEP docs for exact operator signatures
When it happens
Trigger: Calling PREV with a first argument that is not a CEPFieldRef, e.g. PREV(1) or PREV(some expression) in the DEFINE clause, or invoking the StateLocator/prev path programmatically with a non-CEPFieldRef opr1.
Common situations: Misremembering PREV syntax and passing a constant or computed expression instead of a column reference; generated SQL from an ORM/tool that emits unsupported argument shapes.
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 second argument of the prev operation should be a…
- 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/b7d9452079635687.
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:566
"the function is not supported for now: " + operator.getCepKind().toString());
}
} else {
throw new IllegalStateException(
"the right side CEP operation is not legal: " + inputOperation.getClass().toString());
}
}
/* 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 patternVarView on GitHub (pinned to 12126d8942)