flowable/flowable-engine · error · FlowableIllegalArgumentException

There can only be one reactivation listener on a case model,

Error message

There can only be one reactivation listener on a case model, not multiple ones. Use a start form on the listener, if there are several options on how to reactivate a case and use conditions to handle the different options on reactivation.

What it means

During CMMN XML conversion, a ReactivateEventListener is registered on the Case model. The converter enforces at most one reactivation listener per case; a second one raises FlowableIllegalArgumentException with guidance to use start forms and conditions instead.

Source

Thrown at modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/BaseCmmnXmlConverter.java:57

    public BaseElement convertToCmmnModel(XMLStreamReader xtr, ConversionHelper conversionHelper) {
        BaseElement baseElement = convert(xtr, conversionHelper);
        if (baseElement != null) {

            baseElement.setId(xtr.getAttributeValue(null, CmmnXmlConstants.ATTRIBUTE_ID));
            CmmnXmlUtil.addXMLLocation(baseElement, xtr);

            if (baseElement instanceof CmmnElement cmmnElement) {
                conversionHelper.setCurrentCmmnElement(cmmnElement);
            }

            if (baseElement instanceof Criterion criterion) {
                conversionHelper.getCmmnModel().addCriterion(criterion.getId(), criterion);
            }

            // the reactivate event listener is a very specific user event listener in need to be registered in the case model
            if (baseElement instanceof ReactivateEventListener) {
                if (conversionHelper.getCurrentCase().getReactivateEventListener() != null) {
                    throw new FlowableIllegalArgumentException(
                        "There can only be one reactivation listener on a case model, not multiple ones. Use a start form on the listener, "
                        + "if there are several options on how to reactivate a case and use conditions to handle the different options on reactivation.");
                }
                conversionHelper.getCurrentCase().setReactivateEventListener((ReactivateEventListener) baseElement);
            }
        }
        return baseElement;
    }

    protected abstract BaseElement convert(XMLStreamReader xtr, ConversionHelper conversionHelper);

    protected void elementEnd(XMLStreamReader xtr, ConversionHelper conversionHelper) {
        if (hasChildElements()) {
            conversionHelper.removeCurrentCmmnElement();
        }
    }

}

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Keep exactly one ReactivateEventListener per case and delete duplicates
  2. Add a start form on the single listener to choose a reactivation option
  3. Use reactivation conditions on the listener to branch between options
  4. Split into multiple cases if the reactivation logic genuinely requires separate models

Example fix

// before (XML)
<reactivateEventListener id="react1"/>
<reactivateEventListener id="react2"/>
// after
<reactivateEventListener id="react1">
  <extensionElements>
    <flowable:formField .../>
  </extensionElements>
</reactivateEventListener>
Defensive patterns

Strategy: validation

Validate before calling

int reactivateListeners = countElements(cmmnXml, "reactivateEventListener");
if (reactivateListeners > 1) throw new IllegalArgumentException("Only one reactivateEventListener allowed per case");

Try / catch

try { cmmnXmlConverter.convertToCmmnModel(provider); } catch (FlowableIllegalArgumentException e) { throw new DeploymentException("Invalid case model: " + e.getMessage(), e); }

Prevention

When it happens

Trigger: Parsing/deploying a CMMN XML case file that contains two or more reactivate event listener elements within the same case model.

Common situations: Hand-editing or merging CMMN XML so the listener is duplicated; modeling multiple reactivation entry points in one case; copy-pasting a reactivate listener between cases/fragments.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/19678dac35b6ed69. Report an issue: GitHub.