{"record":{"id":"085a590ac284a743","repo":"Activiti/Activiti","slug":"timer-needs-configuration-either-timedate-timecy","errorCode":null,"errorMessage":"Timer needs configuration (either timeDate, timeCycle or timeDuration is needed) (\" + timerEventDefinition.getId() + \")","messagePattern":"Timer needs configuration \\(either timeDate, timeCycle or timeDuration is needed\\) \\(\" \\+ timerEventDefinition\\.getId\\(\\) \\+ \"\\)","errorType":"exception","errorClass":"ActivitiException","httpStatus":null,"severity":"error","filePath":"activiti-core/activiti-engine/src/main/java/org/activiti/engine/impl/util/TimerUtil.java","lineNumber":88,"sourceCode":"        if (StringUtils.isNotEmpty(timerEventDefinition.getTimeDate())) {\n            businessCalendarRef = DueDateBusinessCalendar.NAME;\n            expression = expressionManager.createExpression(timerEventDefinition.getTimeDate());\n        } else if (StringUtils.isNotEmpty(timerEventDefinition.getTimeCycle())) {\n            businessCalendarRef = CycleBusinessCalendar.NAME;\n            expression = expressionManager.createExpression(timerEventDefinition.getTimeCycle());\n        } else if (StringUtils.isNotEmpty(timerEventDefinition.getTimeDuration())) {\n            businessCalendarRef = DurationBusinessCalendar.NAME;\n            expression = expressionManager.createExpression(timerEventDefinition.getTimeDuration());\n        }\n\n        if (StringUtils.isNotEmpty(timerEventDefinition.getCalendarName())) {\n            businessCalendarRef = timerEventDefinition.getCalendarName();\n            Expression businessCalendarExpression = expressionManager.createExpression(businessCalendarRef);\n            businessCalendarRef = businessCalendarExpression.getValue(scopeForExpression).toString();\n        }\n\n        if (expression == null) {\n            throw new ActivitiException(\n                \"Timer needs configuration (either timeDate, timeCycle or timeDuration is needed) (\" +\n                timerEventDefinition.getId() +\n                \")\"\n            );\n        }\n\n        BusinessCalendar businessCalendar = processEngineConfiguration\n            .getBusinessCalendarManager()\n            .getBusinessCalendar(businessCalendarRef);\n\n        String dueDateString = null;\n        Date duedate = null;\n\n        Object dueDateValue = expression.getValue(scopeForExpression);\n        if (dueDateValue instanceof String) {\n            dueDateString = (String) dueDateValue;\n        } else if (dueDateValue instanceof Date) {\n            duedate = (Date) dueDateValue;","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/Activiti/Activiti/blob/56435b1a97deeafdc09dd40074b056c89fba5a8a/activiti-core/activiti-engine/src/main/java/org/activiti/engine/impl/util/TimerUtil.java#L70-L106","documentation":"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.","triggerScenarios":"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).","commonSituations":"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).","solutions":["Add a <timeDate>, <timeCycle> or <timeDuration> child to the timerEventDefinition in the BPMN XML","If the timer uses an expression like ${timeout}, ensure that variable has a value before the timer node executes","Set a process variable default (e.g. via an initialization listener or start form) so the expression never resolves to null"],"exampleFix":"// before\n<intermediateCatchEvent id=\"wait\"><timerEventDefinition id=\"td\"/></intermediateCatchEvent>\n// after\n<intermediateCatchEvent id=\"wait\"><timerEventDefinition id=\"td\"><timeDuration>PT10M</timeDuration></timerEventDefinition></intermediateCatchEvent>","handlingStrategy":"validation","validationCode":"// BPMN check\nif (!xml.contains(\"timeDate\") && !xml.contains(\"timeCycle\") && !xml.contains(\"timeDuration\")) throw new IllegalArgumentException(\"timerEventDefinition needs timeDate/timeCycle/timeDuration\");","typeGuard":null,"tryCatchPattern":"try { runtimeService.startProcessInstanceByKey(key, vars); } catch (ActivitiException e) { if (e.getMessage().contains(\"Timer needs configuration\")) { /* fix BPMN or missing variable */ } throw e; }","preventionTips":["Always include one of timeDate/timeCycle/timeDuration in timer event definitions","If timer values come from variables, initialize defaults at process start","Validate BPMN XML with the model API before deployment"],"tags":["bpmn","timer","configuration","activiti"],"backgroundTag":"missing-required-config-field","analyzedSha":"56435b1a97deeafdc09dd40074b056c89fba5a8a","analyzedAt":"2026-09-09T21:00:06.703Z","contentChangedAt":"2026-09-09T21:00:06.703Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}