{"record":{"id":"261969a871c2fba5","repo":"jeecgboot/JeecgBoot","slug":"l-option-is-not-valid-here-pos-i","errorCode":null,"errorMessage":"'L' option is not valid here. (pos=${i})","messagePattern":"'L' option is not valid here\\. \\(pos=(.+?)\\)","errorType":"validation","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":759,"sourceCode":"            throws ParseException {\n\n        int end = -1;\n        int i = pos;\n\n        if (i >= s.length()) {\n            addToSet(val, end, -1, type);\n            return i;\n        }\n\n        char c = s.charAt(pos);\n\n        if (c == 'L') {\n            if (type == DAY_OF_WEEK) {\n                if(val < 1 || val > 7)\n                    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(val);\n            i++;\n            return i;\n        }\n\n        if (c == 'W') {\n            if (type != DAY_OF_MONTH) {\n                throw new ParseException(\"'W' option is not valid here. (pos=\" + i + \")\", i);\n            }\n            if(val > 31)\n                throw new ParseException(\"The 'W' option does not make sense with values larger than 31 (max number of days in a month)\", i);\n            nearestWeekdays.add(val);\n            i++;\n            return i;\n        }\n","sourceCodeStart":741,"sourceCodeEnd":777,"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#L741-L777","documentation":"Thrown when the 'L' (last) character appears in a cron field that is not day-of-week. In this particular CronExpression implementation, 'L' is only implemented for DAY_OF_WEEK within this code path — using it in any other field type (second, minute, hour, day-of-month, month) triggers the error. Note that standard Quartz also allows 'L' for day-of-month, but this fork's parser does not handle that here.","triggerScenarios":"A cron expression where 'L' appears after a numeric value in any field except day-of-week — e.g., day-of-month field '15L', hour field '8L', or minute field '0L'. The parser reads the value, then encounters 'L' as the next character with type != DAY_OF_WEEK.","commonSituations":"Developer expects 'L' to work for day-of-month ('0 0 0 L * ?') as it does in upstream Quartz but this fork doesn't support it in this branch; copy-paste from a Quartz reference that documents 'L' for day-of-month.","solutions":["Move the 'L' modifier to the day-of-week field only (e.g., '0 0 0 ? * 5L' for last Friday).","For 'last day of month' semantics, check whether this fork's buildTime logic supports 'L' in the day-of-month field via a different code path; if not, use a workaround with '?' in DOW and explicit last-day handling.","Replace the expression with one that uses only supported syntax for the target field."],"exampleFix":"// before\nString cron = \"0 0 0 L * ?\";  // 'L' in day-of-month — not supported here\n// after\nString cron = \"0 0 0 ? * 7L\";  // 'L' only in day-of-week (last Saturday)","handlingStrategy":"validation","validationCode":"// Ensure 'L' only appears in the day-of-week field\nString[] fields = cronExpr.split(\"\\\\s+\");\n// fields[5] is day-of-week (6-field expression)\nfor (int f = 0; f < fields.length; f++) {\n    if (fields[f].contains(\"L\") && f != 5) {\n        throw new IllegalArgumentException(\"'L' is only valid in day-of-week field\");\n    }\n}","typeGuard":"boolean isLOnlyInDayOfWeek(String cron) {\n    String[] fields = cron.trim().split(\"\\\\s+\");\n    for (int f = 0; f < fields.length; f++) {\n        if (fields[f].contains(\"L\") && f != 5) return false;\n    }\n    return true;\n}","tryCatchPattern":"try {\n    CronExpression cron = new CronExpression(expr);\n} catch (ParseException e) {\n    if (e.getMessage().contains(\"'L' option is not valid here\")) {\n        // inform user 'L' must be in day-of-week field\n    }\n    throw e;\n}","preventionTips":["Remember the field order: sec min hr DOM month DOW [year].","Only place 'L' in the DOW field in this implementation.","Use a cron expression linter/validator in the UI before saving."],"tags":["cron","validation","scheduling","xxljob","parse"],"backgroundTag":null,"analyzedSha":"96fb33f5ec68516da0b0147da06b2eb0419e063a","analyzedAt":"2026-08-14T00:04:16.786Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}