{"record":{"id":"b97760c094a8fd84","repo":"flowable/flowable-engine","slug":"timer-for-variablecontainer-was-not-configured","errorCode":null,"errorMessage":"Timer for ${variableContainer} was not configured with a valid duration/time, either hand in a java.util.Date, java.time.LocalDate, java.time.LocalDateTime or a java.time.Instant or a org.joda.time.DateTime or a String in format 'yyyy-MM-dd'T'hh:mm:ss'","messagePattern":"Timer for (.+?) was not configured with a valid duration/time, either hand in a java\\.util\\.Date, java\\.time\\.LocalDate, java\\.time\\.LocalDateTime or a java\\.time\\.Instant or a org\\.joda\\.time\\.DateTime 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/util/TimerUtil.java","lineNumber":189,"sourceCode":"                    \"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. \",\n                    expression.getExpressionText(), variableContainer);\n            // JodaTime support\n            duedate = ((DateTime) dueDateValue).toDate();\n\n        } else if (dueDateValue instanceof Duration) {\n            dueDateString = ((Duration) dueDateValue).toString();\n\n        } else if (dueDateValue instanceof Instant) {\n            duedate = Date.from((Instant) dueDateValue);\n\n        } else if (dueDateValue instanceof LocalDate) {\n            duedate = Date.from(((LocalDate) dueDateValue).atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());\n\n        } else if (dueDateValue instanceof LocalDateTime) {\n            duedate = Date.from(((LocalDateTime) dueDateValue).atZone(ZoneId.systemDefault()).toInstant());\n\n        } else if (dueDateValue != null) {\n            throw new FlowableException(\n                    \"Timer for \" + variableContainer + \" was not configured with a valid duration/time, either hand in a java.util.Date, java.time.LocalDate, java.time.LocalDateTime or a java.time.Instant or a org.joda.time.DateTime or a String in format 'yyyy-MM-dd'T'hh:mm:ss'\");\n        }\n\n        if (duedate == null && dueDateString != null) {\n            duedate = businessCalendar.resolveDuedate(dueDateString);\n        }\n\n        TimerJobEntity timer = null;\n        if (duedate != null) {\n\n            timer = processEngineConfiguration.getJobServiceConfiguration().getTimerJobService().createTimerJob();\n            timer.setJobType(JobEntity.JOB_TYPE_TIMER);\n            timer.setRevision(1);\n            timer.setJobHandlerType(jobHandlerType);\n            timer.setJobHandlerConfiguration(jobHandlerConfig);\n            timer.setExclusive(true);\n            timer.setRetries(processEngineConfiguration.getAsyncExecutorNumberOfRetries());\n            timer.setDuedate(duedate);","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/util/TimerUtil.java#L171-L207","documentation":"TimerUtil.createTimerEntity evaluates the timer's due-date expression and accepts only java.util.Date, LocalDate, LocalDateTime, Instant, org.joda.time.DateTime, or a parseable date String. Any other non-null value is rejected with this FlowableException because no due date can be derived.","triggerScenarios":"A timer definition's timeDate (or resolved dueDateValue) expression returns e.g. a Long timestamp, Integer, Calendar, or an arbitrary object that matches none of the supported instanceof branches in createTimerEntity.","commonSituations":"Setting the timer date variable to epoch millis (Long) instead of Date; process variables holding dates as Strings in non-'yyyy-MM-dd'T'hh:mm:ss' formats; using ZonedDateTime which is not in the supported list; values produced by custom expression functions.","solutions":["Store the variable as java.util.Date, LocalDate, LocalDateTime, Instant, or DateTime, or as a String in 'yyyy-MM-dd'T'hh:mm:ss' format.","Convert at assignment: Date.from(instant) or Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()).","Adjust the expression to perform the conversion, e.g. ${dateTimeUtil.toDate(myValue)}.","If using ZonedDateTime, convert it: Date.from(zdt.toInstant()) before the timer sees it."],"exampleFix":"// before\nexecution.setVariable(\"dueAt\", System.currentTimeMillis());\n// after\nexecution.setVariable(\"dueAt\", new Date());","handlingStrategy":"type-guard","validationCode":"Object v = execution.getVariable(\"dueDateVar\");\nboolean ok = v instanceof Date || v instanceof LocalDate || v instanceof LocalDateTime || v instanceof Instant || v instanceof DateTime || (v instanceof String);\nif (!ok) throw new IllegalArgumentException(\"timer dueDate variable must be Date/LocalDate/LocalDateTime/Instant/DateTime/String\");","typeGuard":"boolean isSupportedDueDate(Object o) { return o == null || o instanceof Date || o instanceof LocalDate || o instanceof LocalDateTime || o instanceof Instant || o instanceof org.joda.time.DateTime || o instanceof String; }","tryCatchPattern":"try { /* trigger timer */ } catch (FlowableException e) { if (e.getMessage().contains(\"was not configured with a valid duration/time\")) log.error(\"Bad timer date type: {}\", e.getMessage()); else throw e; }","preventionTips":["Store timer dates as java.util.Date (or the documented ISO string)","Convert epoch millis/ZonedDateTime before setting the process variable","Type-check variables in custom expression functions that feed timers"],"tags":["flowable","timer","type-mismatch","date"],"backgroundTag":"type-mismatch","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}