flowable/flowable-engine · error · FlowableScriptEvaluationException
scriptTrace
Error message
scriptTrace
What it means
ScriptingEngines.evaluate catches exceptions thrown during script evaluation, builds a scriptTrace, and throws FlowableScriptEvaluationException(scriptTrace, e) unless the root cause is already a FlowableException (which is rethrown as-is). The thrown message text is 'scriptTrace' because the exception message is the trace string, not a fixed literal. This is the engine-level wrapper around all script failures.
Solutions
- Read the scriptTrace embedded in FlowableScriptEvaluationException to identify the failing script and location.
- Inspect getRootCause / cause chain for the underlying ScriptException details.
- Fix the script content, bindings, or register the missing scripting engine per the root cause.
- Register a ScriptTraceListener/ScriptErrorListener during development to log traces on every failure.
Example fix
// before (swallowing the trace)
catch (Exception e) { log.error("script failed"); }
// after
catch (FlowableScriptEvaluationException e) {
log.error("Script failed. Trace:\n{}\nRoot cause:", e.getMessage(), ExceptionUtils.getRootCause(e));
} Defensive patterns
Strategy: try-catch
Try / catch
try {
scriptingEngines.evaluate(script, language, resolver, scopeContainer, inputVariableContainer, storeScriptVariables);
} catch (FlowableScriptEvaluationException e) {
log.error("Script failed. Trace:\n{}\nRoot cause:", e.getMessage(), org.apache.commons.lang3.exception.ExceptionUtils.getRootCause(e), e);
throw e;
} Prevention
- Register a ScriptTraceListener in development environments to capture traces on every failure.
- Always log ExceptionUtils.getRootCause(e) for these exceptions.
- Validate scripts at process-deployment time with a dry-run evaluation.
- Pin the JDK and scripting engine versions to match what the scripts were written for.
When it happens
Trigger: Any failure during script evaluation (ScriptException, engine lookup failure, script syntax/runtime error) that reaches ScriptingEngines.evaluate, including via evaluateScript, renderTaskForm, renderStartForm, or executeScript entry points.
Common situations: Broken script in a BPMN script task; missing scripting engine; script referencing missing variables; debugging via the trace to find which script and line failed.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- e.getMessage()
- problem evaluating script
- A script is required
- Can't find scripting engine for '" + language + "'
- Can't find scripting engine for
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/f85aa5bb8e9b2ab0.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/scripting/ScriptingEngines.java:86
enhanceScriptTrace(request, scriptTrace);
notifyScriptTraceListener(scriptSuccessListener, scriptTrace);
}
return evaluationResult;
} catch (FlowableScriptException e) {
DefaultScriptTrace scriptTrace = DefaultScriptTrace.errorTrace(Duration.ofNanos(System.nanoTime() - startNanos), request, e);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Caught exception evaluating script for {}. {}{}{}", request.getScopeContainer(), request.getLanguage(), System.lineSeparator(),
request.getScript());
}
enhanceScriptTrace(request, scriptTrace);
if (scriptErrorListener != null) {
notifyScriptTraceListener(scriptErrorListener, scriptTrace);
}
Throwable rootCause = ExceptionUtils.getRootCause(e);
if (rootCause instanceof FlowableException) {
throw (FlowableException) rootCause;
}
throw new FlowableScriptEvaluationException(scriptTrace, e);
}
}
protected void notifyScriptTraceListener(ScriptTraceListener listener, ScriptTrace scriptTrace) {
try {
listener.onScriptTrace(scriptTrace);
} catch (Exception e) {
LOGGER.warn("Exception while executing scriptTraceListener: {} with {}", listener, scriptTrace, e);
}
}
protected void enhanceScriptTrace(ScriptEngineRequest request, DefaultScriptTrace scriptTrace) {
if (defaultTraceEnhancer != null) {
defaultTraceEnhancer.enhanceScriptTrace(scriptTrace);
}
if (request.getTraceEnhancer() != null) {
request.getTraceEnhancer().enhanceScriptTrace(scriptTrace);
}View on GitHub (pinned to d6d39ce1c6)