flowable/flowable-engine · error · IllegalArgumentException

Pre upgrade java delegate can't be empty or null.

Error message

Pre upgrade java delegate can't be empty or null.

What it means

setPreUpgradeJavaDelegate requires a non-empty delegate class name when no other pre-upgrade task is configured. Passing null or an empty string gives the document nothing to execute, so it throws IllegalArgumentException.

Solutions

  1. Pass a fully qualified JavaDelegate class name, e.g. setPreUpgradeJavaDelegate("com.acme.MyPreUpgradeDelegate")
  2. Guard with StringUtils.isNotEmpty before calling
  3. Skip the setter when no pre-upgrade delegate is needed

Example fix

// before
document.setPreUpgradeJavaDelegate(config.get("preUpgradeDelegate")); // may be empty
// after
if (StringUtils.isNotEmpty(config.get("preUpgradeDelegate"))) {
    document.setPreUpgradeJavaDelegate(config.get("preUpgradeDelegate"));
}
Defensive patterns

Strategy: validation

Validate before calling

if (delegateClass == null || delegateClass.trim().isEmpty()) {
    throw new IllegalArgumentException("preUpgradeJavaDelegate class name required");
}

Type guard

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

Try / catch

try {
    document.setPreUpgradeJavaDelegate(delegateClass);
} catch (IllegalArgumentException e) {
    log.warn("Skipping pre-upgrade delegate: {}", e.getMessage());
}

Prevention

When it happens

Trigger: Calling setPreUpgradeJavaDelegate(null) or setPreUpgradeJavaDelegate("") on a ProcessInstanceMigrationDocumentImpl with no preUpgradeScript or preUpgradeJavaDelegateExpression set.

Common situations: Reading the delegate class name from config/JSON where the field is missing or blank; string concatenation producing an empty value; placeholder not substituted.

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/9d03256a25281e2c. Report an issue: GitHub.

Appendix: source

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

    public void setPreUpgradeScript(Script script) {
        if (this.preUpgradeJavaDelegate == null && this.preUpgradeJavaDelegateExpression == null) {
            if (script != null) {
                this.preUpgradeScript = script;
            } else {
                throw new IllegalArgumentException("Pre upgrade script can't be null.");
            }
        } else {
            throw new IllegalArgumentException("Pre upgrade script can't be set when another pre-upgrade task was already specified.");
        }
    }

    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.");
        }
    }

View on GitHub (pinned to d6d39ce1c6)