flowable/flowable-engine · error · IllegalArgumentException
Post upgrade script can't be null.
Error message
Post upgrade script can't be null.
What it means
Flowable's ProcessInstanceMigrationDocument rejects a null post-upgrade Script. When building a migration document, calling setPostUpgradeScript to define a script executed after instance migration requires a non-null Script instance; the setter explicitly throws IllegalArgumentException otherwise, so a requested post-upgrade task is never silently ignored.
Solutions
- Ensure the Script instance is constructed before calling setPostUpgradeScript (e.g. new ScriptImpl(...)).
- If no post-upgrade work is needed, do not call the setter at all instead of passing null.
- If a delegate is more appropriate, use setPostUpgradeJavaDelegate or setPostUpgradeJavaDelegateExpression instead.
Example fix
// before
Script script = maybeGetScript(); // may return null
document.setPostUpgradeScript(script);
// after
Script script = maybeGetScript();
if (script != null) {
document.setPostUpgradeScript(script);
} Defensive patterns
Strategy: validation
Validate before calling
if (script == null) { throw new IllegalArgumentException("script must be set before setPostUpgradeScript"); } Type guard
boolean isValidScript(Script s) { return s != null; } Try / catch
try {
document.setPostUpgradeScript(script);
} catch (IllegalArgumentException e) {
logger.error("Invalid post-upgrade script configuration", e);
} Prevention
- Null-check the Script before calling the setter
- Only call the setter when a post-upgrade step is genuinely required
- Set only one post-upgrade task kind (script, delegate, or expression)
When it happens
Trigger: Calling ProcessInstanceMigrationDocument.setPostUpgradeScript(script) with script == null while no postUpgradeJavaDelegate or postUpgradeJavaDelegateExpression has been set yet (i.e. via the builder's build path that routes to this setter).
Common situations: Conditionally building a Script (e.g. from optional config) and passing the null result; deserializing a migration document where the script element was absent; copy-pasting builder code and forgetting to instantiate the Script object.
Related errors
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/e6882a2e192fcf37.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/migration/ProcessInstanceMigrationDocumentImpl.java:126
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.");
}
}
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.");
}
}
View on GitHub (pinned to d6d39ce1c6)