flowable/flowable-engine · error · FlowableIllegalStateException

Cannot create 'script' task listener. Missing ScriptInfo.

Error message

Cannot create 'script' task listener. Missing ScriptInfo.

What it means

DefaultListenerFactory.createScriptTypeTaskListener builds a ScriptTaskListener for a 'script'-type Flowable task listener, but the listener model carries no ScriptInfo (script text/language). The factory refuses to build a listener with nothing to execute and throws FlowableIllegalStateException. It is a BPMN parse-time configuration error, not a runtime execution failure.

Source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/parser/factory/DefaultListenerFactory.java:118

        return new DelegateExpressionTaskListener(expressionManager.createExpression(listener.getImplementation()), createFieldDeclarations(listener.getFieldExtensions()));
    }

    @Override
    public TransactionDependentTaskListener createTransactionDependentDelegateExpressionTaskListener(FlowableListener listener) {
        return new DelegateExpressionTransactionDependentTaskListener(expressionManager.createExpression(listener.getImplementation()));
    }

    @Override
    public TaskListener createScriptTypeTaskListener(FlowableListener listener) {
        if (listener.getScriptInfo() != null) {
            ScriptTypeTaskListener scriptListener = new ScriptTypeTaskListener(
                    createExpression(listener.getScriptInfo().getLanguage()),
                    listener.getScriptInfo().getScript());
            Optional.ofNullable(listener.getScriptInfo().getResultVariable())
                    .ifPresent(resultVar -> scriptListener.setResultVariable(createExpression(resultVar)));
            return scriptListener;
        } else {
            throw new FlowableIllegalStateException("Cannot create 'script' task listener. Missing ScriptInfo.");
        }
    }

    protected Expression createExpression(Object value) {
        return value instanceof String ? expressionManager.createExpression((String) value) : new FixedValue(value);
    }

    @Override
    public ExecutionListener createClassDelegateExecutionListener(FlowableListener listener) {
        return classDelegateFactory.create(listener.getImplementation(), createFieldDeclarations(listener.getFieldExtensions()));
    }

    @Override
    public ExecutionListener createExpressionExecutionListener(FlowableListener listener) {
        return new ExpressionExecutionListener(expressionManager.createExpression(listener.getImplementation()));
    }

    @Override

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Add the <flowable:script language="javascript"><![CDATA[...]]></flowable:script> element inside the task listener in the BPMN XML.
  2. When building the FlowableListener programmatically, call setScriptInfo with a ScriptInfo containing language and script before parsing/deployment.
  3. Validate the BPMN XML for listeners whose implementation type is 'script' but which lack a script child, before deployment.
  4. If the listener should not run a script, change the implementation type to class, expression, or delegate-expression instead.

Example fix

// before
FlowableListener listener = new FlowableListener();
listener.setEvent("create");
listener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_SCRIPT);
// after
FlowableListener listener = new FlowableListener();
listener.setEvent("create");
listener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_SCRIPT);
listener.setScriptInfo(new ScriptInfo("javascript", "println('hi')", null));
Defensive patterns

Strategy: validation

Validate before calling

if (listener.getImplementationType().equals(ImplementationType.IMPLEMENTATION_TYPE_SCRIPT)
        && (listener.getScriptInfo() == null
            || listener.getScriptInfo().getScript() == null)) {
    throw new IllegalArgumentException("script task listener requires scriptInfo with script text");
}

Type guard

boolean hasScriptInfo = l != null
        && ImplementationType.IMPLEMENTATION_TYPE_SCRIPT.equals(l.getImplementationType())
        && l.getScriptInfo() != null;

Try / catch

try {
    deploymentBuilder.deploy();
} catch (FlowableIllegalStateException e) {
    if (e.getMessage().contains("Missing ScriptInfo")) {
        // fix the listener definition before redeploying
    } else { throw e; }
}

Prevention

When it happens

Trigger: A FlowableListener with implementationType 'script' is parsed (e.g. <flowable:taskListener event="..." > with a script child or programmatic FlowableListener) but listener.getScriptInfo() returns null — no script element or ScriptInfo was attached to the listener definition.

Common situations: Hand-written or template-generated BPMN XML where the <script> block inside the task listener was omitted or misnamed; building listener models programmatically (e.g. via the Flowable model API) and forgetting setScriptInfo; XML transformations that drop child elements of the listener.

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