flowable/flowable-engine · error · FlowableIllegalArgumentException
language is required
Error message
language is required
What it means
FlowableScriptEvaluationRequest.evaluate() re-validates the request before executing: if the language field was never set (null or empty) it throws FlowableIllegalArgumentException('language is required'). This catches requests built without calling language() at all, in contrast to the builder-time check in language().
Solutions
- Always call language(<engineName>) before evaluate() on the request builder.
- If language comes from external config, resolve it before constructing the request and fail early.
- Add an assertion/test that the builder chain includes language().
Example fix
// before
FlowableScriptEvaluationRequest req = new FlowableScriptEvaluationRequest().script("return 1;");
req.evaluate();
// after
FlowableScriptEvaluationRequest req = new FlowableScriptEvaluationRequest()
.language("javascript")
.script("return 1;");
req.evaluate(); Defensive patterns
Strategy: validation
Validate before calling
if (language == null || language.trim().isEmpty()) {
throw new IllegalStateException("Cannot evaluate script: language was never set on the request");
} Type guard
boolean isEvaluableRequest(FlowableScriptEvaluationRequest r) { return r != null && r.getLanguage() != null && !r.getLanguage().isEmpty(); } Try / catch
try {
return request.evaluate();
} catch (FlowableIllegalArgumentException e) {
throw new IllegalStateException("Script request incomplete: " + e.getMessage(), e);
} Prevention
- Build requests in a single fluent chain so setters cannot be skipped.
- Wrap builder construction in a factory method that enforces both language and script.
- Add a builder-contract unit test.
When it happens
Trigger: Building a FlowableScriptEvaluationRequest (e.g. via chained fluent setters skipping language()) and calling evaluate(); or a request deserialized/copied without the language field.
Common situations: Programmatic script evaluation where the fluent call chain was assembled conditionally and the language branch was skipped; reflection/copy of request objects losing the field.
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
- A script is required
- script is required
- A resource name is mandatory
- An event definition key is mandatory
- language is empty
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/749228fec70243b1.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/scripting/JSR223FlowableScriptEngine.java:190
return this;
}
@Override
public FlowableScriptEvaluationRequest inputVariableContainer(VariableContainer inputVariableContainer) {
this.inputVariableContainer = inputVariableContainer;
return this;
}
@Override
public FlowableScriptEvaluationRequest storeScriptVariables() {
this.storeScriptVariables = true;
return this;
}
@Override
public ScriptEvaluation evaluate() throws FlowableScriptException {
if (StringUtils.isEmpty(language)) {
throw new FlowableIllegalArgumentException("language is required");
}
if (StringUtils.isEmpty(script)) {
throw new FlowableIllegalArgumentException("script is required");
}
ScriptEngine scriptEngine = getEngineByName(language);
Bindings bindings = createBindings();
try {
Object result = scriptEngine.eval(script, bindings);
return new ScriptEvaluationImpl(resolver, result);
} catch (ScriptException e) {
throw new FlowableScriptException(e.getMessage(), e);
}
}
protected Bindings createBindings() {
return new ScriptBindings(Collections.singletonList(resolver), scopeContainer, inputVariableContainer, storeScriptVariables);View on GitHub (pinned to d6d39ce1c6)