{"record":{"id":"48c87f634c91fbea","repo":"jeecgboot/JeecgBoot","slug":"illegal-cron-expression-format-e","errorCode":null,"errorMessage":"Illegal cron expression format ({e})","messagePattern":"Illegal cron expression format \\((.+?)\\)","errorType":"exception","errorClass":"ParseException","httpStatus":null,"severity":"error","filePath":"jeecg-boot/jeecg-server-cloud/jeecg-visual/jeecg-cloud-xxljob/src/main/java/com/xxl/job/admin/business/scheduler/cron/CronExpression.java","lineNumber":531,"sourceCode":"            }\n\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.\", 0);\n                }\n            }\n        } catch (ParseException pe) {\n            throw pe;\n        } catch (Exception e) {\n            throw new ParseException(\"Illegal cron expression format (\"\n                    + e + \")\", 0);\n        }\n    }\n\n    protected int storeExpressionVals(int pos, String s, int type)\n            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') && (!s.equals(\"L\")) && (!s.equals(\"LW\")) && (!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) {","sourceCodeStart":513,"sourceCodeEnd":549,"githubUrl":"https://github.com/jeecgboot/JeecgBoot/blob/96fb33f5ec68516da0b0147da06b2eb0419e063a/jeecg-boot/jeecg-server-cloud/jeecg-visual/jeecg-cloud-xxljob/src/main/java/com/xxl/job/admin/business/scheduler/cron/CronExpression.java#L513-L549","documentation":"Thrown by the outer catch-all in CronExpression.buildExpression(): any non-ParseException raised while tokenizing the 6-7 cron fields (NumberFormatException, StringIndexOutOfBoundsException, etc.) is wrapped and rethrown as a ParseException. It indicates the parser hit an unexpected internal failure on a structurally malformed expression, so the original cause is concatenated into the message via {e}. Because {e} is the raw exception, the actionable detail lives in its class name and message, not in this generic header.","triggerScenarios":"Constructing 'new CronExpression(expr)' (or XxlJob scheduling a job whose cron field fails). Concrete producers: a field that is empty or has a trailing operator like '0 0 0 /5 * ?', a substring index overrun when a field has <3 chars but starts with A-Z, or a numeric parse on a non-numeric token that slips past the earlier alpha branch. Any RuntimeException during storeExpressionVals/getValue that is not itself a ParseException lands here.","commonSituations":"Operators pasting a cron string from a tutorial that uses Linux crond syntax (5 fields, e.g. '0 5 * * *') into a Quartz/xxl-job field that expects 6-7 fields; missing or duplicate spaces between fields; a copy/paste that drops a trailing segment; upgrading xxl-job across a version where a previously tolerated field shape now throws.","solutions":["Read the wrapped exception in {e}: its class (e.g. NumberFormatException, StringIndexOutOfBoundsException) tells you which field/token is at fault, then fix that specific token.","Confirm the expression has the 6 or 7 Quartz fields (sec min hour dom month dow [year]) separated by single spaces, not the 5-field Linux crond format.","Validate the expression in isolation with 'new CronExpression(cleaned)' inside a unit test before persisting it as a job schedule.","If the cause still is unclear, enable DEBUG on the xxl-job admin to log the raw cron string at submission time and re-parse it locally."],"exampleFix":"// before - 5-field Linux cron fed to Quartz parser\nString cron = \"0 5 * * *\";  // throws Illegal cron expression format\nCronExpression ce = new CronExpression(cron);\n\n// after - 6-field Quartz cron (sec min hour dom month dow)\nString cron = \"0 0 5 * * ?\";\nCronExpression ce = new CronExpression(cron);","handlingStrategy":"try-catch","validationCode":"// Validate a cron expression before persisting it as a job schedule.\n// Returns null on success, or a human-readable reason on failure.\npublic static String validateCron(String expr) {\n    if (expr == null || expr.trim().isEmpty()) return \"cron expression is empty\";\n    String[] fields = expr.trim().split(\"\\\\s+\");\n    if (fields.length < 6 || fields.length > 7) {\n        return \"expected 6 or 7 fields (sec min hour dom month dow [year]), got \" + fields.length;\n    }\n    try {\n        new com.xxl.job.admin.business.scheduler.cron.CronExpression(expr);\n        return null; // ok\n    } catch (java.text.ParseException e) {\n        return e.getMessage();\n    }\n}","typeGuard":"// Lightweight structural type guard before invoking the parser.\n// True only for plausible Quartz cron shapes.\npublic static boolean looksLikeQuartzCron(String expr) {\n    if (expr == null) return false;\n    String[] f = expr.trim().split(\"\\\\s+\");\n    if (f.length < 6 || f.length > 7) return false;\n    java.util.regex.Pattern p = java.util.regex.Pattern.compile(\"[0-9*/,\\\\-?LW#A-Za-z]+\");\n    for (String field : f) if (!p.matcher(field).matches()) return false;\n    return true;\n}","tryCatchPattern":"try {\n    CronExpression ce = new CronExpression(userCron);\n    // ... register schedule with ce\n} catch (java.text.ParseException e) {\n    // 280 surfaces the wrapped cause inside e.getMessage(); surface it to the user.\n    log.warn(\"Invalid cron '{}' from user: {}\", userCron, e.getMessage());\n    throw new IllegalArgumentException(\"Invalid schedule expression: \" + e.getMessage(), e);\n}","preventionTips":["Always run user-supplied cron strings through new CronExpression(expr) in a unit test before saving them to the job config table.","Reject 5-field Linux crond strings at the controller boundary (require 6-7 fields).","Log the exact cron string that failed so the wrapped cause in {e} can be diagnosed.","Provide a cron builder UI that emits valid Quartz syntax rather than accepting free text."],"tags":["cron","xxl-job","parse-error","validation","scheduler"],"backgroundTag":null,"analyzedSha":"96fb33f5ec68516da0b0147da06b2eb0419e063a","analyzedAt":"2026-08-14T00:04:16.786Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}