{"record":{"id":"9f5c8fb4435849c4","repo":"Activiti/Activiti","slug":"the-w-option-does-not-make-sense-with-values-lar","errorCode":null,"errorMessage":"The 'W' option does not make sense with values larger than 31 (max number of days in a month)","messagePattern":"The 'W' option does not make sense with values larger than 31 \\(max number of days in a month\\)","errorType":"exception","errorClass":"ParseException","httpStatus":null,"severity":"error","filePath":"activiti-core/activiti-engine/src/main/java/org/activiti/engine/impl/calendar/CronExpression.java","lineNumber":581,"sourceCode":"            if (type == DAY_OF_WEEK) {\n                if (val < 1 || val > 7) throw new ParseException(\"Day-of-Week values must be between 1 and 7\", -1);\n                lastdayOfWeek = true;\n            } else {\n                throw new ParseException(\"'L' option is not valid here. (pos=\" + i + \")\", i);\n            }\n            TreeSet<Integer> set = getSet(type);\n            set.add(Integer.valueOf(val));\n            i++;\n            return i;\n        }\n\n        if (c == 'W') {\n            if (type == DAY_OF_MONTH) {\n                nearestWeekday = true;\n            } else {\n                throw new ParseException(\"'W' option is not valid here. (pos=\" + i + \")\", i);\n            }\n            if (val > 31) throw new ParseException(\n                \"The 'W' option does not make sense with values larger than 31 (max number of days in a month)\",\n                i\n            );\n            TreeSet<Integer> set = getSet(type);\n            set.add(Integer.valueOf(val));\n            i++;\n            return i;\n        }\n\n        if (c == '#') {\n            if (type != DAY_OF_WEEK) {\n                throw new ParseException(\"'#' option is not valid here. (pos=\" + i + \")\", i);\n            }\n            i++;\n            try {\n                nthdayOfWeek = Integer.parseInt(s.substring(i));\n                if (nthdayOfWeek < 1 || nthdayOfWeek > 5) {\n                    throw new Exception();","sourceCodeStart":563,"sourceCodeEnd":599,"githubUrl":"https://github.com/Activiti/Activiti/blob/56435b1a97deeafdc09dd40074b056c89fba5a8a/activiti-core/activiti-engine/src/main/java/org/activiti/engine/impl/calendar/CronExpression.java#L563-L599","documentation":"This library's cron parser (a port of Quartz's CronExpression) supports the 'W' suffix on a day-of-month field, meaning 'nearest weekday to the given day'. The value preceding 'W' must be a valid day of a month. Since no month has more than 31 days, any value above 31 is rejected at parse time with a ParseException.","triggerScenarios":"Parsing a cron expression whose DAY_OF_MONTH token ends with 'W' and has a numeric value greater than 31 (e.g. '0 0 0 45W * ?' or '0 0 0 32W * ?'), via storeExpressionVals during CronExpression construction.","commonSituations":"Typo or hand-edited cron string in a timer boundary event or job definition in an Activiti BPMN process; a generated expression built from user input without range validation; copy-paste from another scheduler dialect with different day-of-month semantics.","solutions":["Correct the day-of-month value before 'W' to a number between 1 and 31.","If the intent was 'last day of the month', use 'L' instead of an over-large 'W' value.","Validate the cron string (or bound the user-supplied day value to 1..31) before constructing the CronExpression."],"exampleFix":"// before\nString cron = \"0 0 0 45W * ?\";\nCronExpression ce = new CronExpression(cron);\n// after\nString cron = \"0 0 0 15W * ?\"; // 15W: nearest weekday to the 15th\nCronExpression ce = new CronExpression(cron);","handlingStrategy":"validation","validationCode":"int dayVal = extractDayOfMonthBeforeW(cron); // parse token yourself\nif (dayVal > 31) throw new IllegalArgumentException(\"'W' day-of-month must be 1-31\");","typeGuard":"boolean isValidWeekdaySpec(String token) {\n    int i = token.indexOf('W');\n    if (i < 1) return true;\n    try { return Integer.parseInt(token.substring(0, i)) <= 31; }\n    catch (NumberFormatException e) { return false; }\n}","tryCatchPattern":"try {\n    CronExpression ce = new CronExpression(cron);\n} catch (ParseException e) {\n    if (e.getMessage().contains(\"'W' option\")) {\n        throw new ConfigurationException(\"Invalid day-of-month 'W' value in cron: \" + cron, e);\n    }\n    throw e;\n}","preventionTips":["Never build 'W' expressions from unbounded user input; clamp to 1-31.","Use 'L' for last-day-of-month semantics instead of guessing large 'W' values.","Validate cron strings at configuration load time, not at scheduling time."],"tags":["cron","parse-error","activiti","scheduling"],"backgroundTag":"value-out-of-range","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"}