{"record":{"id":"773bd630c168853f","repo":"flowable/flowable-engine","slug":"timer-activityid-in-variablescope-was-not-co","errorCode":null,"errorMessage":"Timer '{activityId}' in {variableScope} 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'","messagePattern":"Timer '(.+?)' in (.+?) 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'","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/cfg/DefaultInternalJobManager.java","lineNumber":258,"sourceCode":"            activityId = TimerEventHandler.getActivityIdFromConfiguration(jobEntity.getJobHandlerConfiguration());\n            String endDateExpressionString = TimerEventHandler.getEndDateFromConfiguration(jobEntity.getJobHandlerConfiguration());\n\n            if (endDateExpressionString != null) {\n                Expression endDateExpression = processEngineConfiguration.getExpressionManager().createExpression(endDateExpressionString);\n\n                String endDateString = null;\n\n                BusinessCalendar businessCalendar = processEngineConfiguration.getBusinessCalendarManager().getBusinessCalendar(\n                        getBusinessCalendarName(TimerEventHandler.getCalendarNameFromConfiguration(jobEntity.getJobHandlerConfiguration()), variableScope));\n\n                if (endDateExpression != null) {\n                    Object endDateValue = endDateExpression.getValue(variableScope);\n                    if (endDateValue instanceof String) {\n                        endDateString = (String) endDateValue;\n                    } else if (endDateValue instanceof Date) {\n                        jobEntity.setEndDate((Date) endDateValue);\n                    } else {\n                        throw new FlowableException(\"Timer '\" + ((ExecutionEntity) variableScope).getActivityId()\n                                + \"' in \" + variableScope + \" 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'\");\n                    }\n\n                    if (jobEntity.getEndDate() == null) {\n                        jobEntity.setEndDate(businessCalendar.resolveEndDate(endDateString));\n                    }\n                }\n            }\n        }\n\n        int maxIterations = 1;\n        if (jobEntity.getProcessDefinitionId() != null) {\n            org.flowable.bpmn.model.Process process = ProcessDefinitionUtil.getProcess(jobEntity.getProcessDefinitionId());\n            maxIterations = getMaxIterations(process, activityId);\n            if (maxIterations <= 1) {\n                maxIterations = getMaxIterations(process, activityId);\n            }\n        }","sourceCodeStart":240,"sourceCodeEnd":276,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/cfg/DefaultInternalJobManager.java#L240-L276","documentation":"While preparing to delete/reschedule a timer job, DefaultInternalJobManager evaluates the timer's end-date expression against the variable scope and expects the result to be a java.util.Date or a date String. If the expression evaluates to some other type (or an unusable value), the engine throws this FlowableException naming the activity and variable scope. It indicates the timer definition (timer end-date expression) produced an incompatible value.","triggerScenarios":"A timer job with an endDate expression whose getValue(variableScope) returns neither String nor Date — e.g. a process variable holding a Long/Integer timestamp, a ZonedDateTime/OffsetDateTime, or an uninitialized variable flowing through the wrong branch — evaluated in preTimerJobDeleteInternal.","commonSituations":"Setting the timer end-date variable to numeric epoch millis instead of a Date; using java.time types (Instant/ZonedDateTime) which Flowable's expression handling does not convert here; a boundary timer cycle whose end condition variable was never initialized; an EL/Spring expression returning a computed value of the wrong type.","solutions":["Ensure the endDate expression evaluates to java.util.Date or a String in ISO format yyyy-MM-dd'T'hh:mm:ss (convert in code before setting the variable)","If you have epoch millis or java.time types, convert explicitly: new java.util.Date(millis) or Date.from(instant)","Check that the variable referenced by the timer expression is initialized and of the expected type in the execution scope","Test the timer expression in isolation (variable reference vs literal) to confirm what type it returns"],"exampleFix":"// before\nexecution.setVariable(\"endDate\", System.currentTimeMillis());\n\n// after\nexecution.setVariable(\"endDate\", new java.util.Date());\n// or a String:\nexecution.setVariable(\"endDate\", \"2026-09-10T12:00:00\");","handlingStrategy":"type-guard","validationCode":"// before setting the variable that drives the timer end date\nObject v = execution.getVariable(\"endDate\");\nif (!(v instanceof java.util.Date) && !(v instanceof String)) {\n  throw new IllegalArgumentException(\"endDate must be Date or ISO string yyyy-MM-dd'T'hh:mm:ss, got \"\n      + (v == null ? \"null\" : v.getClass().getName()));\n}","typeGuard":"static boolean isValidTimerDate(Object v) {\n  if (v instanceof java.util.Date) return true;\n  if (v instanceof String) {\n    try {\n      new java.text.SimpleDateFormat(\"yyyy-MM-dd'T'HH:mm:ss\").parse((String) v);\n      return true;\n    } catch (Exception e) {\n      return false;\n    }\n  }\n  return false;\n}","tryCatchPattern":"try {\n  runtimeService.setVariable(executionId, \"endDate\", value);\n} catch (FlowableException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"was not configured with a valid duration/time\")) {\n    runtimeService.setVariable(executionId, \"endDate\", new java.util.Date());\n  } else {\n    throw e;\n  }\n}","preventionTips":["Only store java.util.Date or ISO-format strings in variables referenced by timer expressions","Convert epoch millis / java.time types (Instant, ZonedDateTime) to Date before assigning","Initialize timer end-date variables before the timer is created in the flow","Test timer definitions (cycle/duration/end date) in a small deployment before production"],"tags":["flowable","timer","job","type-mismatch","bpmn"],"backgroundTag":"type-mismatch","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}