{"record":{"id":"f2a127e1a33e6244","repo":"flowable/flowable-engine","slug":"timer-expression-timereventlistener-gettimerexp","errorCode":null,"errorMessage":"Timer expression '${timerEventListener.getTimerExpression()}' did not resolve to java.util.Date, org.joda.time.DateTime, java.time.Instant, java.time.LocalDate, java.time.LocalDateTime or an ISO8601 date/duration/repetition string or a cron expression for ${planItemInstance}","messagePattern":"Timer expression '(.+?)' did not resolve to java\\.util\\.Date, org\\.joda\\.time\\.DateTime, java\\.time\\.Instant, java\\.time\\.LocalDate, java\\.time\\.LocalDateTime or an ISO8601 date/duration/repetition string or a cron expression for (.+?)","errorType":"validation","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/behavior/impl/TimerEventListenerActivityBehaviour.java","lineNumber":157,"sourceCode":"\n                    } catch (Exception pe) { }\n\n                }\n\n            } else if (timerValue instanceof Instant) {\n                timerDueDate = Date.from((Instant) timerValue);\n\n            } else if (timerValue instanceof LocalDate) {\n                timerDueDate = Date.from(((LocalDate) timerValue).atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());\n\n            } else if (timerValue instanceof LocalDateTime) {\n                timerDueDate = Date.from(((LocalDateTime) timerValue).atZone(ZoneId.systemDefault()).toInstant());\n\n            }\n        }\n\n        if (timerDueDate == null) {\n            throw new FlowableException(\"Timer expression '\" + timerEventListener.getTimerExpression() + \"' did not resolve to java.util.Date, org.joda.time.DateTime, \"\n                    + \"java.time.Instant, java.time.LocalDate, java.time.LocalDateTime or \"\n                    + \"an ISO8601 date/duration/repetition string or a cron expression for \" + planItemInstance);\n        }\n\n        scheduleTimerJob(commandContext, planItemInstance, timerValue, timerDueDate, isRepeating);\n    }\n\n    protected boolean timerJobForPlanItemInstanceExists(CommandContext commandContext, PlanItemInstanceEntity planItemInstance) {\n\n        // For the same plan item, only one timer job can ever be active at any given time.\n        // Since the DefaultJobManager creates a new timer job on repeat, we need to make sure\n        // we're not creating duplicate timers on the create or initiate transition (which does need to happen on the first repeat).\n        //\n        // The alternative implementation would be to move the repeating timer creation to the onStateTransition on occur,\n        // but this would also require similar logic to look up the previous timer job, as the previous repeat value is needed to calculate the next.\n\n        CmmnEngineConfiguration cmmnEngineConfiguration = CommandContextUtil.getCmmnEngineConfiguration(commandContext);\n        List<TimerJobEntity> jobsByScopeIdAndSubScopeId = cmmnEngineConfiguration.getJobServiceConfiguration().getTimerJobEntityManager()","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/behavior/impl/TimerEventListenerActivityBehaviour.java#L139-L175","documentation":"A timer event listener's timer expression evaluated, but the resulting value is not a supported date/time type or ISO8601/cron string, so no due date could be derived. Flowable accepts Date, Joda DateTime, Instant, LocalDate, LocalDateTime, ISO8601 date/duration/repetition strings, or cron expressions.","triggerScenarios":"handleCreateTransition runs on plan item creation and the expression (e.g. ${dueDate} variable or literal) resolves to a String not in ISO8601/cron format, or to some other object type (Integer, custom bean).","commonSituations":"Case variable holding a wrongly formatted date string like 'tomorrow' or '10-11-2026'; expression pointing to the wrong variable; timezone-dependent formats; version change where new types (cron) are expected but the string is invalid.","solutions":["Fix the expression/variable so it resolves to one of the supported types, or an ISO8601 duration/date (e.g. PT1H, 2026-09-10T12:00:00Z) or cron string","If using a String variable, parse it in Java to java.util.Date or java.time type and store that as the variable","Log the resolved timerValue at runtime (or evaluate the expression in a test) to see the actual type/value","For repetition, use valid ISO8601 repetition format like R/PT10M or R10/PT10M"],"exampleFix":"// before\nruntimeService.setVariable(caseInstanceId, \"due\", \"10/09/2026\");\n// after\nruntimeService.setVariable(caseInstanceId, \"due\", java.time.LocalDateTime.of(2026, 9, 10, 12, 0));","handlingStrategy":"validation","validationCode":"const supported = [Date, java.time.Instant, java.time.LocalDateTime, java.time.LocalDate];\nconst v = runtimeService.getVariable(caseInstanceId, timerVar);\nif (typeof v === 'string' && !/^P|^R\\d*\\/|^\\d{4}-\\d{2}-\\d{2}/.test(v)) throw new Error('timer value not ISO8601/cron: ' + v);","typeGuard":"function isSupportedTimerValue(v) { return v instanceof Date || v instanceof java.time.Instant || v instanceof java.time.temporal.Temporal || (typeof v === 'string' && /^[PR]/.test(v)); }","tryCatchPattern":"try {\n  cmmnRuntimeService.startCaseInstance(...);\n} catch (e) {\n  if (e.getMessage?.().includes(\"did not resolve to java.util.Date\")) { /* fix timer variable, restart */ }\n  else throw e;\n}","preventionTips":["Store timer values as java.util.Date or java.time types, never free-form strings","Test all timer expressions against sample variable values","Document accepted ISO8601/cron formats for users setting timer variables"],"tags":["cmmn","timer","expression","date"],"backgroundTag":"invalid-date-format","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}