flowable/flowable-engine · error · IllegalArgumentException

The field 'language' should be set on the TaskListener

Error message

The field 'language' should be set on the TaskListener

What it means

ScriptTypeTaskListener needs both a script and a scripting language to evaluate it. When notify() runs validateParameters() and the 'language' field is null, this IllegalArgumentException is thrown because the engine cannot select a script engine.

Source

Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/listener/ScriptTypeTaskListener.java:85

                .scopeContainer(delegateTask)
                .traceEnhancer(trace -> trace.addTraceTag("type", "taskListener"));
        Object result = scriptingEngines.evaluate(request.build()).getResult();

        if (resultVariable != null) {
            String resultVariable = Objects.toString(this.resultVariable.getValue(delegateTask), null);
            if (resultVariable != null) {
                delegateTask.setVariable(resultVariable, result);
            }
        }
    }

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

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

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

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

    public void setResultVariable(Expression resultVariable) {
        this.resultVariable = resultVariable;
    }

    public Expression getResultVariable() {
        return resultVariable;
    }

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Add the 'language' field to the listener: <flowable:field name="language" stringValue="javascript"/> (or groovy, juel, etc.)
  2. Verify the scripting language name matches a JSR-223 engine available on the classpath
  3. If setting programmatically, call setLanguage(expression) before execution

Example fix

// before
<flowable:taskListener event="complete" class="org.flowable.cmmn.engine.impl.listener.ScriptTypeTaskListener">
  <flowable:field name="script"><flowable:string><![CDATA[println('hi')]]></flowable:string></flowable:field>
</flowable:taskListener>
// after
<flowable:taskListener event="complete" class="org.flowable.cmmn.engine.impl.listener.ScriptTypeTaskListener">
  <flowable:field name="script"><flowable:string><![CDATA[println('hi')]]></flowable:string></flowable:field>
  <flowable:field name="language" stringValue="javascript"/>
</flowable:taskListener>
Defensive patterns

Strategy: validation

Validate before calling

if (!fields.language || !fields.language.stringValue) throw new Error('ScriptTypeTaskListener: missing language field');

Type guard

function hasLanguage(l) { return l != null && l.language != null && l.language.expressionText != null; }

Try / catch

try { runListener(listener); } catch (e) { if (String(e.message).includes("field 'language' should be set")) { configureLanguage(listener); } else { throw e; } }

Prevention

When it happens

Trigger: A ScriptTypeTaskListener definition sets the 'script' field but omits the 'language' field (or the language Expression resolves to null) at execution time.

Common situations: Misspelled field name in CMMN XML (must be exactly 'language'); using a language name not resolvable by the configured script engine manager so the expression evaluates to null; copy-paste of listener XML that dropped the language field.

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/9bc559312329daf0. Report an issue: GitHub.