flowable/flowable-engine · error · IllegalArgumentException

Pre upgrade expression can't be empty or null.

Error message

Pre upgrade expression can't be empty or null.

What it means

setPreUpgradeJavaDelegateExpression requires a non-empty expression string when no other pre-upgrade task is configured. A null or empty expression leaves no pre-upgrade behavior, so it throws IllegalArgumentException.

Solutions

  1. Pass a valid expression, e.g. setPreUpgradeJavaDelegateExpression("${preUpgradeDelegate}")
  2. Guard with StringUtils.isNotEmpty before calling
  3. Skip the setter when no pre-upgrade expression is needed

Example fix

// before
document.setPreUpgradeJavaDelegateExpression(props.getProperty("pre.upgrade.expr")); // may be null
// after
String expr = props.getProperty("pre.upgrade.expr");
if (StringUtils.isNotEmpty(expr)) {
    document.setPreUpgradeJavaDelegateExpression(expr);
}
Defensive patterns

Strategy: validation

Validate before calling

if (expression == null || expression.trim().isEmpty()) {
    throw new IllegalArgumentException("preUpgrade expression required");
}

Type guard

boolean hasText(String s) { return s != null && !s.trim().isEmpty(); }

Try / catch

try {
    document.setPreUpgradeJavaDelegateExpression(expression);
} catch (IllegalArgumentException e) {
    log.warn("No pre-upgrade expression configured: {}", e.getMessage());
}

Prevention

When it happens

Trigger: Calling setPreUpgradeJavaDelegateExpression(null) or ("") on a document with no preUpgradeScript or preUpgradeJavaDelegate set.

Common situations: Expression resolved from a missing config property or empty JSON field; building expressions dynamically that end up blank; typo resolving to empty string.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/migration/ProcessInstanceMigrationDocumentImpl.java:114

    public void setPreUpgradeJavaDelegate(String javaDelegateClassName) {
        if (this.preUpgradeScript == null && this.preUpgradeJavaDelegateExpression == null) {
            if (StringUtils.isNotEmpty(javaDelegateClassName)) {
                this.preUpgradeJavaDelegate = javaDelegateClassName;
            } else {
                throw new IllegalArgumentException("Pre upgrade java delegate can't be empty or null.");
            }
        } else {
            throw new IllegalArgumentException("Pre upgrade java delegate can't be set when another pre-upgrade task was already specified.");
        }
    }

    public void setPreUpgradeJavaDelegateExpression(String expression) {
        if (this.preUpgradeScript == null && this.preUpgradeJavaDelegate == null) {
            if (StringUtils.isNotEmpty(expression)) {
                this.preUpgradeJavaDelegateExpression = expression;
            } else {
                throw new IllegalArgumentException("Pre upgrade expression can't be empty or null.");
            }
        } else {
            throw new IllegalArgumentException("Pre upgrade expression can't be set when another pre-upgrade task was already specified.");
        }
    }

    public void setPostUpgradeScript(Script script) {
        if (this.postUpgradeJavaDelegate == null && this.postUpgradeJavaDelegateExpression == null) {
            if (script != null) {
                this.postUpgradeScript = script;
            } else {
                throw new IllegalArgumentException("Post upgrade script can't be null.");
            }
        } else {
            throw new IllegalArgumentException("Post upgrade script can't be set when another post-upgrade task was already specified.");
        }
    }

View on GitHub (pinned to d6d39ce1c6)