{"record":{"id":"0a3276e39d9206be","repo":"flowable/flowable-engine","slug":"illegal-cron-expression-format","errorCode":null,"errorMessage":"Illegal cron expression format (","messagePattern":"Illegal cron expression format \\(","errorType":"exception","errorClass":"ParseException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/calendar/CronExpression.java","lineNumber":540,"sourceCode":"\n            TreeSet<Integer> dow = getSet(DAY_OF_WEEK);\n            TreeSet<Integer> dom = getSet(DAY_OF_MONTH);\n\n            // Copying the logic from the UnsupportedOperationException below\n            boolean dayOfMSpec = !dom.contains(NO_SPEC);\n            boolean dayOfWSpec = !dow.contains(NO_SPEC);\n\n            if (!dayOfMSpec || dayOfWSpec) {\n                if (!dayOfWSpec || dayOfMSpec) {\n                    throw new ParseException(\n                            \"Support for specifying both a day-of-week AND a day-of-month parameter is not implemented.\",\n                            0);\n                }\n            }\n        } catch (ParseException pe) {\n            throw pe;\n        } catch (Exception e) {\n            throw new ParseException(\"Illegal cron expression format (\" + e + \")\", 0);\n        }\n    }\n\n    protected int storeExpressionVals(int pos, String s, int type) throws ParseException {\n\n        int incr = 0;\n        int i = skipWhiteSpace(pos, s);\n        if (i >= s.length()) {\n            return i;\n        }\n        char c = s.charAt(i);\n        if ((c >= 'A') && (c <= 'Z') && !\"L\".equals(s) && !\"LW\".equals(s) && !s.matches(\"^L-[0-9]*[W]?\")) {\n            String sub = s.substring(i, i + 3);\n            int sval = -1;\n            int eval = -1;\n            if (type == MONTH) {\n                sval = getMonthNumber(sub) + 1;\n                if (sval <= 0) {","sourceCodeStart":522,"sourceCodeEnd":558,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/calendar/CronExpression.java#L522-L558","documentation":"buildExpression catches any non-ParseException thrown while parsing/storing field values (NumberFormatException, StringIndexOutOfBoundsException, etc.) and rethrows it as a ParseException 'Illegal cron expression format (<exception>)'. It is the generic fallback for structurally broken expressions not caught by the specific checks.","triggerScenarios":"new CronExpression(expr, clockReader) with garbage fields that make storeExpressionVals throw — non-numeric tokens like '0 0 abc * *', out-of-range numbers, stray characters such as '0 0 12 */ * ?', truncated ranges like '0 0 5- * ?'.","commonSituations":"Hand-edited BPMN timer XML with typos; values substituted into cron strings (template injection of empty or invalid fragments); locale/paste issues introducing invisible characters.","solutions":["Read the parenthesized cause in the message to identify the exact malformed token and fix it","Validate the expression offline (construct CronExpression in a test or use a cron validator) before deployment","Check for empty/whitespace fragments when the cron is built from templates or variables","Ensure numeric fields stay within range (seconds/minutes 0-59, hours 0-23, days 1-31, months 1-12/JAN-DEC, days-of-week 1-7/SUN-SAT)"],"exampleFix":"// before\nString cron = \"0 0 \" + hour + \" * * ?\"; // hour may be \"\" or \"abc\"\n// after\nint h = Integer.parseInt(hour); // throws NumberFormatException early, and:\nif (h < 0 || h > 23) throw new IllegalArgumentException(\"hour out of range: \" + h);\nString cron = \"0 0 \" + h + \" * * ?\";","handlingStrategy":"validation","validationCode":"// ranges and values per field\nint[][] limits = {{0,59},{0,59},{0,23},{1,31},{1,12},{1,7}};\n// validate each numeric token of field i against limits[i] before constructing CronExpression","typeGuard":null,"tryCatchPattern":"try { new CronExpression(expr, clockReader); }\ncatch (ParseException e) { if (e.getMessage().startsWith(\"Illegal cron expression format\")) { log.error(\"Structurally broken cron: {}\", expr, e); } throw e; }","preventionTips":["Check numeric ranges: sec/min 0-59, hour 0-23, dom 1-31, month 1-12, dow 1-7","Avoid template substitution that can inject empty strings into cron fields","Reject stray characters (repeated '/', '-', missing operands) with a regex pre-check","Test every cron string in CI with new CronExpression(...)"],"tags":["cron","format","parsing","flowable"],"backgroundTag":"invalid-cron-expression","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"}