flowable/flowable-engine · error · ActivitiIllegalArgumentException
Timer ' ' was not configured with a valid duration/time
Error message
Timer '${activityId}' was not configured with a valid duration/time What it means
TimerDeclarationImpl.prepareTimerEntity resolves the timer description from a field/expression; if the resolved description is null, the business calendar would NPE later, so the engine throws ActivitiIllegalArgumentException early stating the timer activity has no valid duration/time configured. It guards the case where the timeDuration/timeDate expression evaluates to nothing.
Solutions
- Set the variable referenced by the timer expression before reaching the timer activity
- Use a literal ISO-8601 duration in the BPMN (e.g. PT10M) instead of a nullable expression
- Fix the expression/bean so it always returns a non-null Date or duration string
- Add a default in the expression, e.g. ${dueDate != null ? dueDate : 'PT1H'}
Example fix
// before (BPMN)
<timeDuration>${delayDuration}</timeDuration> // variable never set
// after
runtimeService.setVariable(executionId, "delayDuration", "PT30M");
// or: <timeDuration>PT30M</timeDuration> Defensive patterns
Strategy: validation
Validate before calling
Object v = runtimeService.getVariable(executionId, "delayDuration");
if (v == null) throw new IllegalStateException("Timer duration variable must be set before reaching the timer"); Type guard
boolean hasTimerValue(VariableScope scope, Expression timerExpr) {
return timerExpr != null && timerExpr.getValue(scope) != null;
} Try / catch
try {
processEngine.getRuntimeService().startProcessInstanceByKey(key, vars);
} catch (ActivitiIllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().contains("valid duration/time")) { /* fix timer config */ }
else throw e;
} Prevention
- Prefer literal ISO-8601 durations in BPMN over nullable expressions
- Initialize all variables referenced by timer expressions at process start
- Model-review timer definitions for expression nullability
When it happens
Trigger: A timer event definition whose timeDuration/timeDate/timeCycle expression evaluates to null at runtime, e.g. ${missingVar} referencing an unset variable, and no valid ISO-8601 duration is available.
Common situations: Variable used in the timer expression not set before the flow reaches the timer; typo in expression variable; conditional timer definition where the field resolves to null; wrong expression returning void/null.
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
- Category expression does not resolve to a string
- ' didn't resolve to a Collection
- completionCondition ' ' does not evaluate to a boolean value
- Could not find matching FlowElement for activityId " +…
- Could not resolve loopCardinality expression
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/8ba7764eec48701e.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/jobexecutor/TimerDeclarationImpl.java:134
// evaluating variables but other context, evaluating should happen nevertheless
VariableScope scopeForExpression = executionEntity;
if (scopeForExpression == null) {
scopeForExpression = NoExecutionVariableScope.getSharedInstance();
}
String calendarNameValue = type.calendarName;
if (this.calendarNameExpression != null) {
calendarNameValue = (String) this.calendarNameExpression.getValue(scopeForExpression);
}
BusinessCalendar businessCalendar = Context
.getProcessEngineConfiguration()
.getBusinessCalendarManager()
.getBusinessCalendar(calendarNameValue);
if (description == null) {
// Prevent NPE from happening in the next line
throw new ActivitiIllegalArgumentException("Timer '" + executionEntity.getActivityId() + "' was not configured with a valid duration/time");
}
String endDateString = null;
String dueDateString = null;
Date duedate = null;
Date endDate = null;
if (endDateExpression != null && !(scopeForExpression instanceof NoExecutionVariableScope)) {
Object endDateValue = endDateExpression.getValue(scopeForExpression);
if (endDateValue instanceof String) {
endDateString = (String) endDateValue;
} else if (endDateValue instanceof Date) {
endDate = (Date) endDateValue;
} else if (endDateValue instanceof DateTime) {
// Joda DateTime support
duedate = ((DateTime) endDateValue).toDate();
} else {
throw new ActivitiException("Timer '" + executionEntity.getActivityId() + "' was not configured with a valid duration/time, either hand in a java.util.Date or a String in format 'yyyy-MM-dd'T'hh:mm:ss'");View on GitHub (pinned to d6d39ce1c6)