{"record":{"id":"9f88d8a6b780e4a9","repo":"apache/beam","slug":"the-second-argument-of-the-prev-operation-should-be-a","errorCode":null,"errorMessage":"the second argument of the prev operation should be a decimal. Provided: ${class}","messagePattern":"the second argument of the prev operation should be a decimal\\. Provided: (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/impl/nfa/NFA.java","lineNumber":571,"sourceCode":"      }\n    }\n\n    /* below are function implementations */\n\n    // represents the PREV operation\n    private CEPLiteral prev(\n        CEPOperation opr1,\n        CEPLiteral opr2,\n        EventPointer curPointer,\n        Event curEvent,\n        Event inputEvent) {\n      if (opr1.getClass() != CEPFieldRef.class) {\n        throw new IllegalStateException(\n            \"the first argument of the PREV operation should be a field reference. Provided: \"\n                + opr1.getClass().toString());\n      }\n      if (opr2.getTypeName() != Schema.TypeName.DECIMAL) {\n        throw new IllegalStateException(\n            \"the second argument of the prev operation should be a decimal. Provided: \"\n                + opr2.getClass().toString());\n      }\n      // if the second argument is 0, return the current event\n      if (opr2.getDecimal().intValue() == 0) {\n        return inputEvent.toCEPLiteral((CEPFieldRef) opr1);\n      }\n      // for the starting event, return null\n      if (curEvent == null) {\n        return null;\n      }\n      CEPFieldRef fieldRef = (CEPFieldRef) opr1;\n      String alpha = fieldRef.getAlpha(); // the patternVar\n      int lastNumber = opr2.getDecimal().intValue();\n      EventPointer iterPointer = curPointer.copy();\n\n      while (curEvent != null && iterPointer.getPatternVar().equals(alpha) && lastNumber > 0) {\n        iterPointer = curEvent.getPrevPointer(iterPointer);","sourceCodeStart":553,"sourceCodeEnd":589,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/impl/nfa/NFA.java#L553-L589","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nPREV(PRICE, '1')\n// after\nPREV(PRICE, 1)","handlingStrategy":"validation","validationCode":"if (prevOffset.getTypeName() != Schema.TypeName.DECIMAL) {\n  throw new IllegalArgumentException(\"PREV offset must be a decimal literal\");\n}","typeGuard":"boolean isDecimalLiteral(CEPOperation op) {\n  return op instanceof CEPLiteral && ((CEPLiteral) op).getTypeName() == Schema.TypeName.DECIMAL;\n}","tryCatchPattern":"try {\n  runCepQuery(pattern);\n} catch (IllegalStateException e) {\n  if (e.getMessage().startsWith(\"the second argument of the prev operation\")) {\n    // correct the offset literal type\n  } else throw e;\n}","preventionTips":["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"],"tags":["sql","cep","argument-type","decimal"],"backgroundTag":"type-mismatch","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}