{"record":{"id":"15841a4b78e8b542","repo":"flowable/flowable-engine","slug":"unrecognised-transactionstate","errorCode":null,"errorMessage":"Unrecognised TransactionState {}","messagePattern":"Unrecognised TransactionState (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/event/FlowableEventSupport.java","lineNumber":154,"sourceCode":"        if (transactionContext == null) {\n            return;\n        }\n        \n        ExecuteEventListenerTransactionListener transactionListener = new ExecuteEventListenerTransactionListener(listener, event); \n        if (listener.getOnTransaction().equalsIgnoreCase(TransactionState.COMMITTING.name())) {\n            transactionContext.addTransactionListener(TransactionState.COMMITTING, transactionListener);\n            \n        } else if (listener.getOnTransaction().equalsIgnoreCase(TransactionState.COMMITTED.name())) {\n            transactionContext.addTransactionListener(TransactionState.COMMITTED, transactionListener);\n            \n        } else if (listener.getOnTransaction().equalsIgnoreCase(TransactionState.ROLLINGBACK.name())) {\n            transactionContext.addTransactionListener(TransactionState.ROLLINGBACK, transactionListener);\n            \n        } else if (listener.getOnTransaction().equalsIgnoreCase(TransactionState.ROLLED_BACK.name())) {\n            transactionContext.addTransactionListener(TransactionState.ROLLED_BACK, transactionListener);\n            \n        } else {\n            LOGGER.warn(\"Unrecognised TransactionState {}\", listener.getOnTransaction());\n        }\n    }\n\n    protected synchronized void addTypedEventListener(FlowableEventListener listener, FlowableEventType type) {\n        List<FlowableEventListener> listeners = typedListeners.get(type);\n        if (listeners == null) {\n            // Add an empty list of listeners for this type\n            listeners = new CopyOnWriteArrayList<>();\n            typedListeners.put(type, listeners);\n        }\n\n        if (!listeners.contains(listener)) {\n            listeners.add(listener);\n        }\n    }\n}\n","sourceCodeStart":136,"sourceCodeEnd":171,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/event/FlowableEventSupport.java#L136-L171","documentation":"In dispatchTransactionEventListener, the listener's getOnTransaction() string is compared (case-insensitively against COMMITTING/ROLLINGBACK/ROLLED_BACK, but case-SENSITIVELY here) against TransactionState enum names. If it matches none, the transaction listener is never registered and only a warning is logged — the listener silently never fires.","triggerScenarios":"A listener registered via addTransactionEventListener or with onTransaction set returns a string that is not exactly COMMITTING, ROLLINGBACK, or ROLLED_BACK (e.g. 'COMMITTED', 'rolled_back', 'committing' with different casing, or a custom value).","commonSituations":"Typo or wrong casing in a programmatic listener registration; a subclass overrides getOnTransaction() with an unexpected constant; version changes introduce new TransactionState handling the custom string doesn't match.","solutions":["Set the listener's transaction state using TransactionState enum names exactly: TransactionState.COMMITTING.name(), ROLLINGBACK, or ROLLED_BACK","Check for case mismatches — the final else branch does equalsIgnoreCase on earlier branches but the whole chain must match one of the three states; use the enum constant instead of a hand-written string","Log/print listener.getOnTransaction() at registration time to confirm the value","If you need a state not supported (e.g. COMMITTED), register a transaction listener directly on the TransactionContext instead"],"exampleFix":"// before\nlistener.setOnTransaction(\"COMMITTED\"); // never matches -> warn, listener never fires\n// after\nlistener.setOnTransaction(TransactionState.ROLLED_BACK.name());","handlingStrategy":"validation","validationCode":"TransactionState[] valid = {TransactionState.COMMITTING, TransactionState.ROLLINGBACK, TransactionState.ROLLED_BACK};\nString onTx = listener.getOnTransaction();\nboolean ok = onTx != null && Arrays.stream(valid).anyMatch(s -> s.name().equalsIgnoreCase(onTx));\nif (!ok) throw new IllegalArgumentException(\"Unsupported onTransaction: \" + onTx);","typeGuard":"boolean isValidTransactionState(String s) {\n    return s != null && (TransactionState.COMMITTING.name().equalsIgnoreCase(s)\n        || TransactionState.ROLLINGBACK.name().equalsIgnoreCase(s)\n        || TransactionState.ROLLED_BACK.name().equalsIgnoreCase(s));\n}","tryCatchPattern":null,"preventionTips":["Always derive the value from TransactionState.name() instead of typing strings","Write a registration-time assertion validating getOnTransaction()","Avoid overriding getOnTransaction() with custom constants"],"tags":["flowable","event-listener","transaction","enum-mismatch"],"backgroundTag":"invalid-enum-value","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}