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
- Pass a valid expression, e.g. setPreUpgradeJavaDelegateExpression("${preUpgradeDelegate}")
- Guard with StringUtils.isNotEmpty before calling
- 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
- Resolve expressions from config with defaults or explicit failure earlier
- Validate the expression syntax before setting
- Apply hasText guards to all expression inputs
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
- Pre upgrade expression can't be set when another…
- Pre upgrade java delegate can't be empty or null.
- Cannot migrate process(es), not enough information
- Cannot resolve calledElement expression
- Cannot start a sub process instance. Process model " +…
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)