flowable/flowable-engine · error · FlowableIllegalArgumentException

Priority expression does not resolve to a number: +…

Error message

Priority expression does not resolve to a number: + activeTaskPriority

What it means

The user task's flowable:priority expression resolved to an object that is neither a String nor a Number, so the engine cannot derive an integer priority. This is the else-branch of handlePriority and throws FlowableIllegalArgumentException. (The message references the local field activeTaskPriority in the source, but the offending value is the resolved expression result.)

Solutions

  1. Make the expression return a Number (Integer) directly, e.g. ${bean.priorityValue} returning int
  2. Unwrap the enum/DTO: return the numeric field instead of the object
  3. Coerce in a delegate/execution listener: setVariable to an Integer before the user task
  4. Fix the type of the underlying process variable

Example fix

// before
public Priority getPriority() { return Priority.HIGH; }
// after
public int getPriority() { return 100; }
Defensive patterns

Strategy: type-guard

Validate before calling

Object p = priorityExpr.getValue(execution);
if (p != null && !(p instanceof Number) && !(p instanceof String)) {
    throw new IllegalArgumentException("Priority must be Number or numeric String, got " + p.getClass());
}

Type guard

boolean isNumericPriority(Object v) {
    return v instanceof Number || (v instanceof String && ((String) v).matches("\\d+"));
}

Try / catch

try {
    taskService.complete(taskId, vars);
} catch (FlowableIllegalArgumentException e) {
    if (e.getMessage().contains("Priority expression")) {
        // unwrap the object to its numeric value and retry
    }
}

Prevention

When it happens

Trigger: flowable:priority expression evaluating to Boolean, Map, custom object, or null-adjacent wrapper that is not Number/String.

Common situations: Spring bean method returning a Priority enum or custom DTO; expression returning a Boolean flag mistakenly used as priority; variable set to JSON-serialized object by a preceding service task.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

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

            }
        }
    }

    protected void handlePriority(CreateUserTaskBeforeContext beforeContext, ExpressionManager expressionManager, TaskEntity task, DelegateExecution execution,
            String activeTaskPriority) {
        if (StringUtils.isNotEmpty(beforeContext.getPriority())) {
            final Object priority = expressionManager.createExpression(beforeContext.getPriority()).getValue(execution);
            if (priority != null) {
                if (priority instanceof String) {
                    try {
                        task.setPriority(Integer.valueOf((String) priority));
                    } catch (NumberFormatException e) {
                        throw new FlowableIllegalArgumentException("Priority does not resolve to a number: " + priority, e);
                    }
                } else if (priority instanceof Number) {
                    task.setPriority(((Number) priority).intValue());
                } else {
                    throw new FlowableIllegalArgumentException("Priority expression does not resolve to a number: " + activeTaskPriority);
                }
            }
        }
    }

    protected void handleCategory(CreateUserTaskBeforeContext beforeContext, ExpressionManager expressionManager, TaskEntity task,
            DelegateExecution execution) {
        if (StringUtils.isNotEmpty(beforeContext.getCategory())) {
            String category = null;
            try {
                Object categoryValue = expressionManager.createExpression(beforeContext.getCategory()).getValue(execution);
                if (categoryValue != null) {
                    category = categoryValue.toString();
                }
            } catch (FlowableException e) {
                category = beforeContext.getCategory();
                LOGGER.warn("property not found in task category expression {}", e.getMessage());
            }

View on GitHub (pinned to d6d39ce1c6)