flowable/flowable-engine · error · IllegalArgumentException
Post upgrade expression can't be empty or null.
Error message
Post upgrade expression can't be empty or null.
What it means
setPostUpgradeJavaDelegateExpression requires a non-empty expression string (e.g. "${myDelegateBean}"). Flowable throws IllegalArgumentException when it is null or blank, enforcing that an expression-based post-upgrade task is actually specified.
Source
Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/migration/ProcessInstanceMigrationDocumentImpl.java:150
public void setPostUpgradeJavaDelegate(String javaDelegateClassName) {
if (this.postUpgradeScript == null && this.postUpgradeJavaDelegateExpression == null) {
if (StringUtils.isNotEmpty(javaDelegateClassName)) {
this.postUpgradeJavaDelegate = javaDelegateClassName;
} else {
throw new IllegalArgumentException("Post upgrade java delegate can't be empty or null.");
}
} else {
throw new IllegalArgumentException("Post upgrade java delegate can't be set when another post-upgrade task was already specified.");
}
}
public void setPostUpgradeJavaDelegateExpression(String expression) {
if (this.postUpgradeScript == null && this.postUpgradeJavaDelegate == null) {
if (StringUtils.isNotEmpty(expression)) {
this.postUpgradeJavaDelegateExpression = expression;
} else {
throw new IllegalArgumentException("Post upgrade expression can't be empty or null.");
}
} else {
throw new IllegalArgumentException("Post upgrade expression can't be set when another post-upgrade task was already specified.");
}
}
@Override
public String getMigrateToProcessDefinitionId() {
return migrateToProcessDefinitionId;
}
@Override
public String getMigrateToProcessDefinitionKey() {
return migrateToProcessDefinitionKey;
}
@Override
public Integer getMigrateToProcessDefinitionVersion() {View on GitHub (pinned to d6d39ce1c6)
Solutions
- Pass a valid expression such as "${postUpgradeDelegateBean}".
- Omit the call if no post-upgrade task is required.
- Use setPostUpgradeScript or setPostUpgradeJavaDelegate for the other task types.
Example fix
// before
String expr = System.getProperty("postUpgradeExpression"); // null
document.setPostUpgradeJavaDelegateExpression(expr);
// after
String expr = System.getProperty("postUpgradeExpression");
if (expr != null && !expr.isBlank()) {
document.setPostUpgradeJavaDelegateExpression(expr);
} Defensive patterns
Strategy: validation
Validate before calling
if (expression == null || expression.isBlank()) { throw new IllegalArgumentException("expression required"); } Type guard
boolean isValidExpression(String s) { return s != null && !s.trim().isEmpty(); } Try / catch
try {
document.setPostUpgradeJavaDelegateExpression(expr);
} catch (IllegalArgumentException e) {
logger.error("Post-upgrade expression missing", e);
} Prevention
- Verify the expression property exists before use
- Fail fast when expression config is blank
- Set only one post-upgrade task kind per document
When it happens
Trigger: Calling setPostUpgradeJavaDelegateExpression(null) or an empty/whitespace string while no postUpgradeScript or postUpgradeJavaDelegate has been set yet.
Common situations: Expression values resolved from missing Spring bean properties or empty environment entries; generated migration configs with unfilled expression placeholders.
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
- version must be positive
- text is null
- Unknown property used in expression:
- Unknown method used in expression:
- Error while evaluating expression:
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/94eeaf2b221b6503.
Report an issue: GitHub.