{"record":{"id":"83e0dc618f788cd3","repo":"flowable/flowable-engine","slug":"cannot-parse-duration","errorCode":null,"errorMessage":"Cannot parse duration","messagePattern":"Cannot parse duration","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/calendar/AdvancedCycleBusinessCalendar.java","lineNumber":116,"sourceCode":"\n        // START is a legacy value that is no longer used, but may still exist in deployed job schedules\n        // Could be used in the future as a start date for a CRON job\n        // String startDate = getValueFrom(\"START\", duedateDescription);\n\n        duedateDescription = removeValueFrom(\"VER\", removeValueFrom(\"START\", removeValueFrom(\"DSTZONE\", duedateDescription))).trim();\n\n        try {\n            LOGGER.info(\"Base Due Date: {}\", duedateDescription);\n\n            Date date = resolvers.get(version == null ? getDefaultScheduleVersion() : Integer.valueOf(version)).resolve(duedateDescription, clockReader,\n                    timeZone == null ? clockReader.getCurrentTimeZone() : TimeZone.getTimeZone(timeZone));\n\n            LOGGER.info(\"Calculated Date: {}\", date == null ? \"Will Not Run Again\" : date);\n\n            return date;\n\n        } catch (Exception e) {\n            throw new FlowableIllegalArgumentException(\"Cannot parse duration\", e);\n        }\n\n    }\n\n    private String getValueFrom(String field, String duedateDescription) {\n        int fieldIndex = duedateDescription.indexOf(field + \":\");\n\n        if (fieldIndex > -1) {\n            int nextWhiteSpace = duedateDescription.indexOf(' ', fieldIndex);\n\n            fieldIndex += field.length() + 1;\n\n            if (nextWhiteSpace > -1) {\n                return duedateDescription.substring(fieldIndex, nextWhiteSpace);\n            } else {\n                return duedateDescription.substring(fieldIndex);\n            }\n        }","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/calendar/AdvancedCycleBusinessCalendar.java#L98-L134","documentation":"Thrown by AdvancedCycleBusinessCalendar.resolveDuedate as FlowableIllegalArgumentException when any part of parsing the cycle/ISO duration description fails (TimeDuration, cron-like expression, or daylight-saving arithmetic) while computing the next due date for a timer. Any exception in the calculation is wrapped with this generic message.","triggerScenarios":"A timer boundary/start event or job with a malformed duedateDescription: bad ISO 8601 duration/cycle (e.g. 'R/PT1H/x'), invalid cron-style fields, wrong ISO string segments, or an expression that the calendar's getValueFrom cannot extract.","commonSituations":"Typos in timer cycle definitions in BPMN XML; using legacy 'R/...' strings mixed with new ISO 8601 repetition syntax; expressions returning null/empty values; locale/timezone issues around DST transitions producing invalid dates.","solutions":["Validate the timer definition string: it must be a valid ISO 8601 cycle (e.g. 'R3/PT10M' or 'R/ISO interval') or valid cron expression supported by the calendar.","Test the exact duedate string with AdvancedCycleBusinessCalendar.resolveDuedate in a unit test to see the wrapped cause (getCause()).","Fix common typos: use 'P'/'PT' prefixes correctly, valid repetition counts, and unambiguous ISO intervals.","If using variable expressions in the timer, ensure they resolve to non-empty valid strings at runtime."],"exampleFix":"// before\n<timeCycle>R/PT1H/2026-13-40T00:00:00Z</timeCycle> <!-- invalid date -->\n// after\n<timeCycle>R/PT1H/2026-12-31T00:00:00Z</timeCycle>","handlingStrategy":"validation","validationCode":"boolean isValidCycle(String duedate) {\n  try { Duration.parse(duedate.startsWith(\"P\") ? duedate : duedate.substring(duedate.indexOf('/') + 1)); return true; }\n  catch (DateTimeParseException e) { return false; }\n}","typeGuard":null,"tryCatchPattern":"try {\n  Date due = calendar.resolveDuedate(duedateDescription);\n} catch (FlowableIllegalArgumentException e) {\n  log.error(\"Invalid timer cycle '{}': {}\", duedateDescription, e.getCause(), e);\n  throw new IllegalArgumentException(\"Fix BPMN timeCycle definition\", e);\n}","preventionTips":["Validate ISO 8601 cycle strings (Rn/PT.., ISO intervals) before deploying BPMN.","Unit-test timer definitions with resolveDuedate and inspect getCause() on failure.","Avoid mixing legacy 'R/...' legacy syntax with new ISO repetition syntax inconsistently.","Ensure expression-based timers always resolve to non-empty valid strings."],"tags":["timer","duedate","iso8601","parsing"],"backgroundTag":"invalid-duration-format","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"}