flowable/flowable-engine · error · FlowableException

Timer needs configuration (either timeDate, timeCycle or tim

Error message

Timer needs configuration (either timeDate, timeCycle or timeDuration is needed) (${id})

What it means

TimerUtil.createTimerEntity requires the timer event definition to define exactly one timing configuration. If, after evaluating timeDate/timeCycle/timeDuration expressions, the resulting timer expression is null, Flowable throws this FlowableException because a timer without any schedule cannot fire.

Source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/util/TimerUtil.java:153

        } 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(variableContainer).toString();
        }

        if (expression == null) {
            throw new FlowableException(
                    "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(variableContainer);
        if (dueDateValue instanceof String) {
            dueDateString = (String) dueDateValue;

        } else if (dueDateValue instanceof Date) {
            duedate = (Date) dueDateValue;

        } else if (dueDateValue instanceof DateTime) {
            JodaDeprecationLogger.LOGGER.warn(
                    "Using Joda-Time DateTime has been deprecated and will be removed in a future version. Timer event listener expression {} in {} resolved to a Joda-Time DateTime. ",

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Add one of <timeDate>, <timeCycle> or <timeDuration> to the timerEventDefinition in the BPMN XML.
  2. Ensure the referenced expression variable is set so the timer expression resolves to a non-null value.
  3. Validate the process definition at deployment time (e.g. with a validator or unit test parsing the model) to catch empty timers early.
  4. If the timer is conditionally needed, model it as a conditional/skip-able path rather than an empty timer definition.

Example fix

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

Strategy: validation

Validate before calling

boolean timerConfigured(TimerEventDefinition d) {
  return StringUtils.isNotEmpty(d.getTimeDate()) || StringUtils.isNotEmpty(d.getTimeCycle()) || StringUtils.isNotEmpty(d.getTimeDuration());
}

Try / catch

try { /* deploy/execute process */ } catch (FlowableException e) { if (e.getMessage().startsWith("Timer needs configuration")) log.error("Timer {} missing timeDate/timeCycle/timeDuration", e.getMessage()); else throw e; }

Prevention

When it happens

Trigger: A boundary/intermediate/start timer event whose timeDate, timeCycle and timeDuration attributes are all absent or whose expressions all evaluate to null; createTimerEntity invoked via TimerUtil.timer during execution of such an event.

Common situations: BPMN XML with a timerEventDefinition missing child elements; timer attributes supplied only via deployment-time substitution that silently failed; refactoring that removed the timeDuration value; dynamic model edits leaving an empty timer definition.

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 flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/d103247fbf0e0c5f. Report an issue: GitHub.