flowable/flowable-engine · error · FlowableIllegalStateException

Cannot create 'script' task listener. Missing ScriptInfo.

Error message

Cannot create 'script' task listener. Missing ScriptInfo.

What it means

DefaultCmmnListenerFactory builds a ScriptTypeTaskListener from a FlowableListener. A script-type listener must carry a ScriptInfo (language + script); if listener.getScriptInfo() returns null the factory cannot construct the listener and throws FlowableIllegalStateException. This indicates malformed listener definition data — typically a model/parse bug or an incorrectly assembled FlowableListener.

Source

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

    public TaskListener createClassDelegateTaskListener(FlowableListener listener) {
        return classDelegateFactory.createLifeCycleListener(listener.getImplementation(), listener.getSourceState(), listener.getTargetState(), listener.getFieldExtensions());
    }

    @Override
    public TaskListener createExpressionTaskListener(FlowableListener listener) {
        return new ExpressionTaskListener(expressionManager.createExpression(listener.getImplementation()));
    }

    @Override
    public TaskListener createDelegateExpressionTaskListener(FlowableListener listener) {
        return new DelegateExpressionTaskListener(expressionManager.createExpression(listener.getImplementation()), listener.getFieldExtensions());
    }

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

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

    @Override
    public PlanItemInstanceLifecycleListener createClassDelegateLifeCycleListener(FlowableListener listener) {
        return classDelegateFactory.create(listener.getImplementation(), listener.getFieldExtensions());
    }

    @Override

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Fix the listener definition so the script element carries both language and script content, then redeploy the case definition.
  2. If building FlowableListener programmatically, call setScriptInfo(ScriptInfo) with non-null language/script before registering the listener.
  3. Validate the deployed case model (parse step) to catch missing ScriptInfo at deploy time instead of runtime.
  4. Check the Flowable version for known parser bugs around script listener metadata if definitions look correct.

Example fix

// before
FlowableListener listener = new FlowableListenerImpl();
listener.setEventType("create");
listener.setOnTransactionType("before-commit");
// after
FlowableListener listener = new FlowableListenerImpl();
listener.setEventType("create");
ScriptInfo scriptInfo = new ScriptInfoImpl("javascript", "task.setVariable('done', true)", null);
listener.setScriptInfo(scriptInfo);
Defensive patterns

Strategy: validation

Validate before calling

if (listener.getScriptInfo() == null || listener.getScriptInfo().getScript() == null || listener.getScriptInfo().getLanguage() == null) {
    throw new IllegalArgumentException("Script task listener requires ScriptInfo with language and script");
}

Type guard

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

Try / catch

try {
    TaskListener tl = listenerFactory.createScriptTypeTaskListener(listener);
} catch (FlowableIllegalStateException e) {
    if (e.getMessage() != null && e.getMessage().contains("Missing ScriptInfo")) {
        throw new ModelValidationException("Listener definition lacks script info; fix case XML", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: createScriptTypeTaskListener(listener) is called for a listener whose type is script but whose ScriptInfo was never populated (e.g. the CMMN XML listener definition lacked script content, or a programmatically built FlowableListener omitted setScriptInfo).

Common situations: Hand-written or dynamically generated CMMN XML with a task listener marked as script but missing <script> details; custom model code building FlowableListener objects without ScriptInfo; parse/upgrade issue where ScriptInfo is dropped.

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