flowable/flowable-engine · error · FlowableException

Error evaluating juel script

Error message

Error evaluating juel script: "${script}" for ${execution}

What it means

ScriptTaskActivityBehavior.executeScript throws this when a JUEL script appears not to have been evaluated: the script engine returned a String identical to the original script text, meaning the expression was echoed back unchanged instead of being resolved. Flowable treats that as a failed evaluation and stops the execution.

Solutions

  1. Verify the script task's language attribute is exactly 'juel' and that the JUEL scripting engine is on the classpath
  2. Wrap the script content in a proper JUEL expression (e.g. ${expr}) if you intended expression evaluation
  3. Check ScriptingEngines configuration for a resolver that may have been removed/renamed after a Flowable version upgrade
  4. Test the same expression with Flowable's expression manager outside the script task to confirm evaluation works

Example fix

// before
<scriptTask scriptFormat="juel"><script>user.name</script></scriptTask>
// after
<scriptTask scriptFormat="juel"><script>${user.name}</script></scriptTask>
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure the script contains an expression marker before executing
if (language.equalsIgnoreCase("juel") && !script.contains("${")) {
    throw new IllegalArgumentException("JUEL script must be an expression: " + script);
}

Try / catch

try {
    execution = taskExecutor.execute(activityId);
} catch (FlowableException e) {
    if (e.getMessage().startsWith("Error evaluating juel script")) {
        // fix script language/expression syntax
    }
}

Prevention

When it happens

Trigger: A script task with language 'juel' whose script source is returned verbatim by scriptingEngines.evaluate — typically when the JUEL engine is not properly registered/selected, or the script contains no expression markers so it is treated as a literal.

Common situations: Misspelled script language (e.g. 'JUEL' handled by a fallback engine), a script with no ${...} expression, or a scripting engine configuration change after upgrading Flowable so the juel engine resolves to a passthrough implementation.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/ScriptTaskActivityBehavior.java:146

                .language(language).scopeContainer(execution);
        builder = storeScriptVariables ? builder.storeScriptVariables() : builder;
        FlowElement flowElement = execution.getCurrentFlowElement();
        if (flowElement instanceof ScriptTask scriptTask) {
            List<IOParameter> inParameters = scriptTask.getInParameters();
            if (inParameters != null && !inParameters.isEmpty()) {
                MapDelegateVariableContainer inputVariableContainer = new MapDelegateVariableContainer();
                IOParameterUtil.processInParameters(inParameters, execution, inputVariableContainer, processEngineConfiguration.getExpressionManager());
                builder.inputVariableContainer(inputVariableContainer);
            } else if (scriptTask.isDoNotIncludeVariables()) {
                builder.inputVariableContainer(VariableContainer.empty());
            }
        }
        ScriptEngineRequest request = builder.build();
        Object result = scriptingEngines.evaluate(request).getResult();

        if (null != result) {
            if ("juel".equalsIgnoreCase(language) && (result instanceof String) && script.equals(result.toString())) {
                throw new FlowableException("Error evaluating juel script: \"" + script + "\" for " + execution);
            }
        }

        if (resultVariable != null) {
            execution.setVariable(resultVariable, result);
        }
    }
}

View on GitHub (pinned to d6d39ce1c6)