flowable/flowable-engine · error · ActivitiIllegalArgumentException
duedate is null
Error message
duedate is null
What it means
JobEntityManager.schedule persists a timer job and requires a valid due date, since the async executor depends on it to decide when to fire. A timer with a null duedate is rejected with ActivitiIllegalArgumentException before insertion.
Solutions
- Ensure the timer definition provides a valid timeDate/timeDuration/timeCycle expression and that referenced process variables are set.
- Set duedate explicitly (e.g., new Date(System.currentTimeMillis() + delay)) before calling schedule.
- Validate/parse the timer expression at deployment time so failures surface at deploy, not runtime.
Example fix
// before TimerJobEntity timer = TimerJobEntity.createAndInsertJob(job); schedule(timer); // duedate null -> throws // after TimerJobEntity timer = TimerJobEntity.createAndInsertJob(job); timer.setDuedate(new Date(System.currentTimeMillis() + Duration.ofMinutes(5).toMillis())); schedule(timer);
Defensive patterns
Strategy: validation
Validate before calling
if (timer.getDuedate() == null) {
timer.setDuedate(computeDuedateFromDefinition(timer));
}
schedule(timer); Type guard
function isSchedulable(timer) {
return timer.getDuedate() instanceof Date;
} Try / catch
try {
jobEntityManager.schedule(timer);
} catch (ActivitiIllegalArgumentException e) {
log.error("Timer {} has no duedate; check its time expression/variables", timer.getId());
} Prevention
- Always set duedate before scheduling programmatically
- Ensure timer event expressions reference defined, non-null process variables
- Validate timer definitions (timeDate/timeDuration/timeCycle) at deployment
When it happens
Trigger: Programmatically creating a TimerJobEntity and calling schedule without setting duedate; a boundary/intermediate timer event whose timeDuration/timeDate expression evaluated to null; custom job creation code copied from examples and partially filled.
Common situations: BPMN timer events using an expression variable that resolves to null at runtime (unset process variable); custom schedulers building timer entities manually; migrating job definitions where the due-date column/logic was dropped.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- jobId is null
- Timer ' ' in was not configured with a valid duration/time…
- Timer ' ' was not configured with a valid duration/time…
- activatedBefore is null
- activity tenant id is null
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/b3c20b7ae8d8bd45.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/persistence/entity/JobEntityManager.java:57
/**
* @author Tom Baeyens
* @author Daniel Meyer
* @author Joram Barrez
*/
public class JobEntityManager extends AbstractManager {
public void send(JobEntity message) {
message.insert();
if (Context.getProcessEngineConfiguration().getAsyncExecutor().isActive()) {
hintAsyncExecutor(message);
}
}
public void schedule(TimerJobEntity timer) {
Date duedate = timer.getDuedate();
if (duedate == null) {
throw new ActivitiIllegalArgumentException("duedate is null");
}
timer.insert();
}
protected void hintAsyncExecutor(Job job) {
AsyncExecutor asyncExecutor = Context.getProcessEngineConfiguration().getAsyncExecutor();
CommandContext commandContext = CommandContextUtil.getCommandContext();
TransactionContext transactionContext = org.flowable.common.engine.impl.context.Context.getTransactionContext();
if (transactionContext != null) {
JobAddedTransactionListener jobAddedTransactionListener = new JobAddedTransactionListener(job, asyncExecutor,
CommandContextUtil.getProcessEngineConfiguration(commandContext).getCommandExecutor());
transactionContext.addTransactionListener(TransactionState.COMMITTED, jobAddedTransactionListener);
} else {
CommandContextCloseListener commandContextCloseListener = new AsyncJobAddedNotification(job, asyncExecutor);View on GitHub (pinned to d6d39ce1c6)