Activiti/Activiti · error · ActivitiException

Timer needs configuration (either timeDate, timeCycle or…

Error message

Timer needs configuration (either timeDate, timeCycle or timeDuration is needed) (" + timerEventDefinition.getId() + ")

What it means

TimerUtil.createTimerEntityForTimerEventDefinition throws ActivitiException when a BPMN timer event definition resolves to a null expression — meaning none of timeDate, timeCycle, or timeDuration yielded a value. Activiti cannot schedule a timer without one of these.

Solutions

  1. Add a <timeDate>, <timeCycle> or <timeDuration> child to the timerEventDefinition in the BPMN XML
  2. If the timer uses an expression like ${timeout}, ensure that variable has a value before the timer node executes
  3. Set a process variable default (e.g. via an initialization listener or start form) so the expression never resolves to null

Example fix

// before
<intermediateCatchEvent id="wait"><timerEventDefinition id="td"/></intermediateCatchEvent>
// after
<intermediateCatchEvent id="wait"><timerEventDefinition id="td"><timeDuration>PT10M</timeDuration></timerEventDefinition></intermediateCatchEvent>
Defensive patterns

Strategy: validation

Validate before calling

// BPMN check
if (!xml.contains("timeDate") && !xml.contains("timeCycle") && !xml.contains("timeDuration")) throw new IllegalArgumentException("timerEventDefinition needs timeDate/timeCycle/timeDuration");

Try / catch

try { runtimeService.startProcessInstanceByKey(key, vars); } catch (ActivitiException e) { if (e.getMessage().contains("Timer needs configuration")) { /* fix BPMN or missing variable */ } throw e; }

Prevention

When it happens

Trigger: A boundary/intermediate timer event or timer start event whose <timeDate>/<timeCycle>/<timeDuration> element is missing, or whose expression evaluates to null (e.g. an expression referencing an empty/unset process variable).

Common situations: BPMN XML hand-edited and timer child element removed; timer duration supplied via a process variable that was never set (e.g. ${timeoutDuration} is null at runtime).

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of Activiti/Activiti@56435b1a97 (2026-09-09). Data as JSON: /api/errors/085a590ac284a743. Report an issue: GitHub.

Appendix: source

Thrown at activiti-core/activiti-engine/src/main/java/org/activiti/engine/impl/util/TimerUtil.java:88

        if (StringUtils.isNotEmpty(timerEventDefinition.getTimeDate())) {
            businessCalendarRef = DueDateBusinessCalendar.NAME;
            expression = expressionManager.createExpression(timerEventDefinition.getTimeDate());
        } else if (StringUtils.isNotEmpty(timerEventDefinition.getTimeCycle())) {
            businessCalendarRef = CycleBusinessCalendar.NAME;
            expression = expressionManager.createExpression(timerEventDefinition.getTimeCycle());
        } else if (StringUtils.isNotEmpty(timerEventDefinition.getTimeDuration())) {
            businessCalendarRef = DurationBusinessCalendar.NAME;
            expression = expressionManager.createExpression(timerEventDefinition.getTimeDuration());
        }

        if (StringUtils.isNotEmpty(timerEventDefinition.getCalendarName())) {
            businessCalendarRef = timerEventDefinition.getCalendarName();
            Expression businessCalendarExpression = expressionManager.createExpression(businessCalendarRef);
            businessCalendarRef = businessCalendarExpression.getValue(scopeForExpression).toString();
        }

        if (expression == null) {
            throw new ActivitiException(
                "Timer needs configuration (either timeDate, timeCycle or timeDuration is needed) (" +
                timerEventDefinition.getId() +
                ")"
            );
        }

        BusinessCalendar businessCalendar = processEngineConfiguration
            .getBusinessCalendarManager()
            .getBusinessCalendar(businessCalendarRef);

        String dueDateString = null;
        Date duedate = null;

        Object dueDateValue = expression.getValue(scopeForExpression);
        if (dueDateValue instanceof String) {
            dueDateString = (String) dueDateValue;
        } else if (dueDateValue instanceof Date) {
            duedate = (Date) dueDateValue;

View on GitHub (pinned to 56435b1a97)