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

  1. Always call language(<engineName>) before evaluate() on the request builder.
  2. If language comes from external config, resolve it before constructing the request and fail early.
  3. 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

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


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)