flowable/flowable-engine · error · FlowableIllegalStateException

'language' evaluated to null for taskListener of type 'scrip

Error message

'language' evaluated to null for taskListener of type 'script'

What it means

ScriptTypeTaskListener executes its script via the ScriptingEngines at runtime. Before doing so it evaluates the configured 'language' expression; if it evaluates to null the engine cannot select a ScriptEngine and throws FlowableIllegalStateException. This means the language attribute/expression on the script task listener did not resolve to a usable value at execution time.

Source

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

    protected Expression resultVariable;

    public ScriptTypeTaskListener() {
    }

    public ScriptTypeTaskListener(Expression language, Expression script) {
        this.script = script;
        this.language = language;
    }

    @Override
    public void notify(DelegateTask delegateTask) {
        validateParameters();

        ScriptingEngines scriptingEngines = CommandContextUtil.getCmmnEngineConfiguration().getScriptingEngines();
        String language = Objects.toString(this.language.getValue(delegateTask), null);
        if (language == null) {
            throw new FlowableIllegalStateException("'language' evaluated to null for taskListener of type 'script'");
        }
        String script = Objects.toString(this.script.getValue(delegateTask), null);
        if (script == null) {
            throw new FlowableIllegalStateException("Script content is null or evaluated to null for taskListener of type 'script'");
        }

        ScriptEngineRequest.Builder request = ScriptEngineRequest.builder()
                .script(script)
                .language(language)
                .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);
            }

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Set the language attribute to a concrete value (e.g. 'javascript', 'groovy', 'juel') in the listener definition, or ensure the referenced variable exists on the task scope.
  2. Validate the CMMN XML so the script listener has both language and script attributes before deployment.
  3. If the language must be dynamic, populate the variable in a prior listener/plan item before the script listener executes.
  4. Confirm the scripting engine for the given language is on the classpath so the value is not discarded downstream.

Example fix

// before (CMMN XML)
<flowable:taskListener event="create" script="task.setVariable('x',1)" />
// after
<flowable:taskListener event="create" language="javascript" script="task.setVariable('x',1)" />
Defensive patterns

Strategy: validation

Validate before calling

String lang = scriptLanguageExpression != null ? String.valueOf(scriptLanguageExpression) : null;
if (lang == null || lang.isBlank()) throw new IllegalArgumentException("Script task listener language must be set");

Type guard

boolean hasLanguage(FlowableListener l) {
    return l.getScriptInfo() != null && l.getScriptInfo().getLanguage() != null && !l.getScriptInfo().getLanguage().isBlank();
}

Try / catch

try {
    // task create triggers script listener
} catch (FlowableIllegalStateException e) {
    if (e.getMessage() != null && e.getMessage().contains("'language' evaluated to null")) {
        log.error("Script listener language unresolved; check variable " + langVarName);
        throw new ConfigurationException("Set a concrete scripting language on the listener", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: notify(delegateTask) evaluates this.language.getValue(delegateTask) and, after Objects.toString(..., null), gets null — the language was configured as a dynamic expression that resolves to null, or was left effectively unset in the listener definition.

Common situations: language set to an expression like ${langVar} where the variable is missing on the delegate task; XML attribute emptied by a template/generator; relying on a default language that is not applied in this code path; case data not populated before the listener fires.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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