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
- Add the language field: <activiti:field name="language" value="groovy"/>.
- Verify the language value matches a ScriptEngine available to the JVM (e.g. javascript, groovy, jython).
- If configuring programmatically, call setLanguage(expression) with a non-null Expression.
- 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
- Always declare the language field together with script in ScriptExecutionListener.
- Confirm the chosen scripting language's engine is on the classpath (e.g. groovy dependency).
- Validate BPMN listener fields with automated tests before deployment.
- Standardize on one scripting language per project to reduce configuration drift.
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
- The field 'script' should be set on the ExecutionListener
- 'language' evaluated to null for listener of type 'script'
- Cannot create 'script' task listener. Missing ScriptInfo.
- Cannot throw process-instance scoped message, since the…
- Cannot throw process-instance scoped signal, since the…
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)