flowable/flowable-engine · error · FlowableException
Timer expression
Error message
Timer expression
What it means
When rescheduling a timer, the command evaluates the new date expression. If the resolved value is not a java.util.Date (neither a literal Date nor a parseable expression result), it throws FlowableException saying the timer expression did not resolve to a Date.
Solutions
- Ensure the referenced variable is a java.util.Date before rescheduling
- Pass a Date object directly instead of a string/expression
- Use an ISO-8601 parseable string if a string must be supplied
- Log and inspect the exception's 'pe' cause by evaluating the expression manually in a test
Example fix
// before
cmmnRuntimeService.setTimerJobDueDate(jobId, "${dueDateString}"); // variable is a String
// after
Date due = new SimpleDateFormat("yyyy-MM-dd").parse("2026-10-01");
cmmnRuntimeService.setTimerJobDueDate(jobId, due); Defensive patterns
Strategy: validation
Validate before calling
Object v = caseVariables.get("dueDateVar");
if (!(v instanceof java.util.Date)) throw new IllegalArgumentException("timer var must be java.util.Date"); Type guard
boolean isResolvableDate(Object v) { return v instanceof java.util.Date; } Try / catch
try { runtimeService.setTimerJobDueDate(jobId, due); } catch (FlowableException e) { log.error("Timer expression did not resolve to Date", e); } Prevention
- Store timer variables as java.util.Date
- Prefer passing literal Date objects
- Test expressions resolving to null
When it happens
Trigger: Passing a new due date as a String expression like '${someDate}' whose variable is missing or not a Date; passing a formatted string not parseable as ISO date; passing an unsupported type (Long, Instant) through the expression.
Common situations: Setting a process/case variable used by the timer expression to a String instead of Date; typos in date format; using java.time types that Flowable's CMMN timer expression resolver does not accept.
Related errors
- Cannot trigger process task plan item instance : reference…
- Category expression does not resolve to a string:
- Could not evaluate collection for repetition rule on plan…
- Delegate expression did not resolve to an implementation of
- Delegate expression did not resolve to an implementation of
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/8309a70c97d8a4ab.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/RescheduleTimerJobCmd.java:120
isRepeating = true;
} else {
// Try to parse as ISO8601 first
try {
timerDueDate = DateUtil.parseDate(newDateValue);
} catch (Exception e) { }
// Try to parse as cron expression
try {
timerDueDate = businessCalendarManager.getBusinessCalendar(CycleBusinessCalendar.NAME).resolveDuedate(newDateValue);
isRepeating = true;
} catch (Exception pe) { }
}
if (timerDueDate == null) {
throw new FlowableException("Timer expression '" + newDateValue + "' did not resolve to java.util.Date for " + planItemInstance);
}
}
CmmnEngineConfiguration cmmnEngineConfiguration = CommandContextUtil.getCmmnEngineConfiguration(commandContext);
JobServiceConfiguration jobServiceConfiguration = cmmnEngineConfiguration.getJobServiceConfiguration();
TimerJobEntity newTimer = timerJobService.createTimerJob();
newTimer.setJobType(timerJob.getJobType());
newTimer.setJobHandlerType(timerJob.getJobHandlerType());
newTimer.setExclusive(true);
newTimer.setRetries(jobServiceConfiguration.getAsyncExecutorNumberOfRetries());
newTimer.setDuedate(timerDueDate);
newTimer.setScopeDefinitionId(timerJob.getScopeDefinitionId());
newTimer.setScopeId(timerJob.getScopeId());
newTimer.setSubScopeId(timerJob.getSubScopeId());
newTimer.setCategory(timerJob.getCategory());
newTimer.setScopeType(timerJob.getScopeType());
newTimer.setElementId(timerJob.getElementId());View on GitHub (pinned to d6d39ce1c6)