flowable/flowable-engine · error · IllegalArgumentException

The field 'language' should be set on the ExecutionListener

Error message

The field 'language' should be set on the ExecutionListener

What it means

Thrown as a plain IllegalArgumentException from ScriptExecutionListener.notify when the listener's 'language' field (an Expression set via <activiti:field name="language">) is null. The scripting engine needs a language name (e.g. javascript, groovy) to select a ScriptEngine for evaluating the script.

Solutions

  1. Add the language field: <activiti:field name="language" value="groovy"/>.
  2. Verify the language value matches a ScriptEngine available to the JVM (e.g. javascript, groovy, jython).
  3. If configuring programmatically, call setLanguage(expression) with a non-null Expression.
  4. Keep a project template/snippet for ScriptExecutionListener that always includes both script and language fields.

Example fix

// before
<activiti:executionListener event="start" class="...ScriptExecutionListener">
  <activiti:field name="script"><activiti:string>execution.setVariable('x', 1);</activiti:string></activiti:field>
</activiti:executionListener>

// after
<activiti:executionListener event="start" class="...ScriptExecutionListener">
  <activiti:field name="script"><activiti:string>execution.setVariable('x', 1);</activiti:string></activiti:field>
  <activiti:field name="language" value="groovy"/>
</activiti:executionListener>
Defensive patterns

Strategy: validation

Validate before calling

assertListenerHasField(processDefinitionXml, "ScriptExecutionListener", "language");
// and confirm the engine exists in the JVM
new ScriptEngineManager().getEngineByName("groovy"); // non-null check in real code

Try / catch

try {
    repositoryService.createDeployment().addInputStream("p.bpmn", xml).deploy();
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("The field 'language' should be set")) {
        logger.error("ScriptExecutionListener missing <activiti:field name=\"language\">");
    }
    throw e;
}

Prevention

When it happens

Trigger: A ScriptExecutionListener is declared with a script field but without the <activiti:field name="language"> element, or the field injects a null Expression.

Common situations: Forgetting the language field when writing the listener XML; misspelling the field name; programmatically building the listener without setLanguage; templates/copy-paste where language was omitted.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/bpmn/listener/ScriptExecutionListener.java:40

public class ScriptExecutionListener implements ExecutionListener {

    private static final long serialVersionUID = 1L;

    private Expression script;

    private Expression language;

    private Expression resultVariable;

    @Override
    public void notify(DelegateExecution execution) {

        if (script == null) {
            throw new IllegalArgumentException("The field 'script' should be set on the ExecutionListener");
        }

        if (language == null) {
            throw new IllegalArgumentException("The field 'language' should be set on the ExecutionListener");
        }

        ScriptingEngines scriptingEngines = Context.getProcessEngineConfiguration().getScriptingEngines();

        Object result = scriptingEngines.evaluate(script.getExpressionText(), language.getExpressionText(), execution);

        if (resultVariable != null) {
            execution.setVariable(resultVariable.getExpressionText(), result);
        }
    }

    public void setScript(Expression script) {
        this.script = script;
    }

    public void setLanguage(Expression language) {
        this.language = language;
    }

View on GitHub (pinned to d6d39ce1c6)