{"record":{"id":"d096f66ddbb376c2","repo":"xuxueli/xxl-job","slug":"l-option-is-not-valid-here-pos","errorCode":null,"errorMessage":"'L' option is not valid here. (pos={})","messagePattern":"'L' option is not valid here\\. \\(pos=(.+?)\\)","errorType":"validation","errorClass":"ParseException","httpStatus":null,"severity":"error","filePath":"xxl-job-admin/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/xuxueli/xxl-job/blob/e74c784f68f81fa89cb350913ef15794865d7b12/xxl-job-admin/src/main/java/com/xxl/job/admin/business/scheduler/cron/CronExpression.java#L741-L777","documentation":"In checkNext, when 'L' follows a numeric value in a field that is NOT Day-of-Week, this error fires. The 'NL' syntax (Nth last weekday) is only valid in the day-of-week field. In the main parse loop, standalone 'L' at the start of a field is handled separately (for day-of-month at line 667); this specific path handles 'L' appearing after a digit.","triggerScenarios":"A cron expression like '0 0 0 5L * ?' where '5L' appears in the day-of-month field. The parser reads 5 as a digit, enters checkNext, finds 'L', and since type != DAY_OF_WEEK, throws at line 759.","commonSituations":"Confusing the day-of-month 'L' (which stands alone as just 'L' or 'L-N') with the day-of-week 'NL' pattern. A developer writes '15L' expecting 'last day' but the parser interprets the digit first.","solutions":["For 'last day of the month' in day-of-month, use standalone 'L' not '15L': '0 0 0 L * ?'.","For 'last occurrence of a weekday' in day-of-week, use 'NL' with N in 1-7: '0 0 0 ? * 6L'.","Move the 'L' modifier to the correct field."],"exampleFix":"// before\n\"0 0 0 5L * ?\"\n// after\n\"0 0 0 L * ?\"","handlingStrategy":"validation","validationCode":"// Reject 'NL' (number followed by L) in any field except day-of-week (index 5)\nString[] parts = cron.trim().split(\"\\\\s+\");\nfor (int idx = 0; idx < parts.length; idx++) {\n    if (parts[idx].matches(\".*\\\\d+L.*\") && idx != 5) {\n        throw new IllegalArgumentException(\"'NL' is only valid in day-of-week (field 5): \" + parts[idx]);\n    }\n}","typeGuard":"boolean isNumberLInDayOfWeekOnly(String[] parts) {\n    for (int idx = 0; idx < parts.length; idx++) {\n        if (parts[idx].matches(\".*\\\\d+L.*\") && idx != 5) return false;\n    }\n    return true;","tryCatchPattern":"try {\n    new CronExpression(cron);\n} catch (ParseException e) {\n    if (e.getMessage().contains(\"'L' option is not valid here\")) {\n        // use standalone 'L' for day-of-month, or move 'NL' to day-of-week\n    }\n}","preventionTips":["Use standalone 'L' for 'last day of month' in day-of-month, not 'NL'.","Reserve 'NL' for day-of-week 'last occurrence of weekday N'.","Document the distinction between day-of-month 'L' and day-of-week 'NL'."],"tags":["cron","validation","quartz","syntax"],"backgroundTag":null,"analyzedSha":"e74c784f68f81fa89cb350913ef15794865d7b12","analyzedAt":"2026-08-14T04:22:43.715Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}