{"record":{"id":"e1f38602233ec360","repo":"jeecgboot/JeecgBoot","slug":"l-not-expected-in-seconds-minutes-or-hours-fiel","errorCode":null,"errorMessage":"'L' not expected in seconds, minutes or hours fields.","messagePattern":"'L' not expected in seconds, minutes or hours fields\\.","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":670,"sourceCode":"                }\n\n                incr = getNumericValue(s, i);\n\n                i++;\n                if (incr > 10) {\n                    i++;\n                }\n                checkIncrementRange(incr, type, i);\n            } else {\n                incr = 1;\n            }\n\n            addToSet(ALL_SPEC_INT, -1, incr, type);\n            return i;\n        } else if (c == 'L') {\n\n            if(type < DAY_OF_MONTH)\n                throw new ParseException(\"'L' not expected in seconds, minutes or hours fields.\", i);\n\n            i++;\n            if (type == DAY_OF_WEEK) {\n                addToSet(7, 7, 0, type);\n            }\n            if (type == DAY_OF_MONTH) {\n                int dom = LAST_DAY_OFFSET_END;\n                boolean nearestWeekday = false;\n                if (s.length() > i) {\n                    c = s.charAt(i);\n                    if (c == '-') {\n                        ValueSet vs = getValue(0, s, i + 1);\n                        int offset = vs.value;\n                        if (offset > MAX_LAST_DAY_OFFSET)\n                            throw new ParseException(\"Offset from last day must be <= \" + MAX_LAST_DAY_OFFSET, i + 1);\n                        dom -= offset;\n                        i = vs.pos;\n                    }","sourceCodeStart":652,"sourceCodeEnd":688,"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#L652-L688","documentation":"'L' means 'last' (last day of month, or last weekday). It is only meaningful for DAY_OF_MONTH and DAY_OF_WEEK. Because field types are numbered SECOND=0, MINUTE=1, HOUR=2, DAY_OF_MONTH=3, the guard 'type < DAY_OF_MONTH' rejects 'L' in the seconds, minutes or hours fields. Using 'L' there is a syntax error.","triggerScenarios":"An 'L' in an early field: 'L * * * * ?' (SECOND), '0 L * * * ?' (MINUTE), '0 0 L * * ?' is valid (HOUR would be invalid too: '0 0 L * * ?' -> HOUR='L' triggers since HOUR=2 < 3). The 'L' for hours is sometimes confused with a 'last hour' concept that Quartz does not support.","commonSituations":"Assuming 'L' means 'last X' for any unit; copy/paste of an 'L' template into the wrong field; UI that lets users pick 'last' without scoping it to day fields.","solutions":["Use 'L' only in the day-of-month field (e.g. '0 0 0 L * ?' = last day of month at 00:00) or day-of-week field ('0 0 0 ? * L' = Saturday).","For 'last second/minute/hour' there is no Quartz equivalent - express it numerically (59, 59, 23).","Validate that 'L' appears only in dom (field 4) or dow (field 6) positions."],"exampleFix":"// before - 'L' in the hour field\nString cron = \"0 0 L * * ?\";  // 'L' not expected in seconds, minutes or hours fields\n\n// after - 23 for last hour, L reserved for day-of-month\nString cron = \"0 0 23 * * ?\";\n// or last day of month\nString cron = \"0 0 0 L * ?\";","handlingStrategy":"validation","validationCode":"// 'L' is legal only in dom (index 3) or dow (index 5).\npublic static String validateLastModifierPlacement(String expr) {\n    String[] f = expr.trim().split(\"\\\\s+\");\n    for (int i = 0; i < f.length && i < 6; i++) {\n        if (f[i].contains(\"L\") && i != 3 && i != 5) {\n            return \"'L' is only allowed in day-of-month or day-of-week, found in field \" + (i + 1);\n        }\n    }\n    return null;\n}","typeGuard":"public static boolean lastModifierOnlyInDayFields(String[] fields) {\n    for (int i = 0; i < fields.length && i < 6; i++) {\n        if (fields[i].contains(\"L\") && i != 3 && i != 5) return false;\n    }\n    return true;\n}","tryCatchPattern":"try {\n    new CronExpression(expr);\n} catch (ParseException e) {\n    if (e.getMessage().contains(\"not expected in seconds\")) {\n        return \"'L' is for day fields only. Use 59/59/23 for last second/minute/hour. \" + e.getMessage();\n    }\n    throw e;\n}","preventionTips":["Forbid 'L' outside the dom/dow positions at the input boundary.","Use explicit numeric maxima (59, 59, 23) for last-second/minute/hour needs.","Document for users that 'L' means 'last day of month / last weekday'."],"tags":["cron","xxl-job","last-modifier","field-validation","parse-error"],"backgroundTag":null,"analyzedSha":"96fb33f5ec68516da0b0147da06b2eb0419e063a","analyzedAt":"2026-08-14T00:04:16.786Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}