{"record":{"id":"19b28160d769320e","repo":"jeecgboot/JeecgBoot","slug":"support-for-specifying-multiple-nth-days-is-not","errorCode":null,"errorMessage":"Support for specifying multiple \"nth\" days is not implemented.","messagePattern":"Support for specifying multiple \"nth\" days is not implemented\\.","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":494,"sourceCode":"\n            int exprOn = SECOND;\n\n            StringTokenizer exprsTok = new StringTokenizer(expression, \" \\t\",\n                    false);\n\n            if(exprsTok.countTokens() > 7) {\n                throw new ParseException(\"Invalid expression has too many terms: \" + expression, -1);\n            }\n\n            while (exprsTok.hasMoreTokens() && exprOn <= YEAR) {\n                String expr = exprsTok.nextToken().trim();\n\n                // throw an exception if L is used with other days of the week\n                if(exprOn == DAY_OF_WEEK && expr.indexOf('L') != -1 && expr.length() > 1  && expr.contains(\",\")) {\n                    throw new ParseException(\"Support for specifying 'L' with other days of the week is not implemented\", -1);\n                }\n                if(exprOn == DAY_OF_WEEK && expr.indexOf('#') != -1 && expr.indexOf('#', expr.indexOf('#') +1) != -1) {\n                    throw new ParseException(\"Support for specifying multiple \\\"nth\\\" days is not implemented.\", -1);\n                }\n\n                StringTokenizer vTok = new StringTokenizer(expr, \",\");\n                while (vTok.hasMoreTokens()) {\n                    String v = vTok.nextToken();\n                    storeExpressionVals(0, v, exprOn);\n                }\n\n                exprOn++;\n            }\n\n            if (exprOn <= DAY_OF_WEEK) {\n                throw new ParseException(\"Unexpected end of expression.\",\n                        expression.length());\n            }\n\n            if (exprOn <= YEAR) {\n                storeExpressionVals(0, \"*\", YEAR);","sourceCodeStart":476,"sourceCodeEnd":512,"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#L476-L512","documentation":"Thrown by CronExpression's parser when the day-of-week field contains more than one '#' character — e.g., 'FRI#2,FRI#4' or '6#1,6#3'. The '#' modifier specifies the 'nth occurrence' of a day in a month (e.g., '6#3' = third Friday). Quartz does not support multiple nth-day specifiers in a single expression. The check detects a second '#' after the first one in the field.","triggerScenarios":"Cron expression like '0 0 12 ? * 6#1,6#3' trying to run on the first and third Friday of each month. Expression like '0 0 6 ? * 1#1,1#3' for first and third Sunday. Any comma-separated day-of-week value containing two or more '#' characters.","commonSituations":"Scheduling bi-weekly or specific-week-of-month jobs that need multiple nth-occurrence rules. Misunderstanding that '#' can only appear once per expression. Building dynamic cron strings that concatenate multiple '#'-based rules.","solutions":["Split into multiple CronTriggers: one for '6#1' (first Friday) and another for '6#3' (third Friday), both targeting the same job.","If the schedule can be expressed as 'every N weeks', consider using a different scheduling strategy (e.g., a simple periodic trigger with date filtering).","Use '6#1' alone if only one nth-occurrence is needed: '0 0 12 ? * 6#1'."],"exampleFix":"// before: multiple # specifiers in one expression — invalid\nString cron = \"0 0 12 ? * 6#1,6#3\";\nCronExpression expr = new CronExpression(cron);\n\n// after: two separate triggers\nCronTrigger firstFriday = TriggerBuilder.newTrigger()\n    .withSchedule(CronScheduleBuilder.cronSchedule(\"0 0 12 ? * 6#1\"))\n    .build();\nCronTrigger thirdFriday = TriggerBuilder.newTrigger()\n    .withSchedule(CronScheduleBuilder.cronSchedule(\"0 0 12 ? * 6#3\"))\n    .build();\nscheduler.scheduleJob(jobDetail, firstFriday);\nscheduler.scheduleJob(jobDetail, thirdFriday);","handlingStrategy":"validation","validationCode":"// Pre-validate day-of-week field for multiple # specifiers\npublic void validateDayOfWeekField(String cronExpression) {\n    String[] fields = cronExpression.trim().split(\"\\\\s+\");\n    if (fields.length >= 6) {\n        String dayOfWeek = fields[5];\n        int hashCount = dayOfWeek.length() - dayOfWeek.replace(\"#\", \"\").length();\n        if (hashCount > 1) {\n            throw new IllegalArgumentException(\n                \"Cannot specify multiple '#' nth-day modifiers: \" + dayOfWeek);\n        }\n    }\n}","typeGuard":"// Check if day-of-week field has at most one # specifier\npublic boolean hasValidNthDaySpecifier(String dow) {\n    if (dow == null || dow.isEmpty()) return true;\n    int hashCount = dow.length() - dow.replace(\"#\", \"\").length();\n    return hashCount <= 1;\n}","tryCatchPattern":"try {\n    CronExpression cron = new CronExpression(expression);\n} catch (ParseException e) {\n    if (e.getMessage().contains(\"nth\")) {\n        throw new IllegalArgumentException(\n            \"Multiple '#' specifiers are not supported. Split into separate triggers.\", e);\n    }\n    throw e;\n}","preventionTips":["Use at most one '#' specifier per cron expression (e.g., '6#3' for third Friday only).","For multiple nth-occurrence rules (e.g., first AND third Friday), create separate triggers.","Validate cron expressions in the admin UI before saving to prevent runtime parse errors.","Educate users on Quartz '#' modifier semantics: dayOfWeek#nthOccurrence."],"tags":["cron","quartz","scheduling","xxl-job","day-of-week"],"backgroundTag":null,"analyzedSha":"96fb33f5ec68516da0b0147da06b2eb0419e063a","analyzedAt":"2026-08-14T00:04:16.786Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}