jeecgboot/JeecgBoot · error · ParseException

Support for specifying both a day-of-week AND a day-of-month

Error message

Support for specifying both a day-of-week AND a day-of-month parameter is not implemented.

What it means

Thrown by CronExpression's parser when both day-of-month and day-of-week fields are specified with actual values (neither is '?'/NO_SPEC). Quartz requires that one of these two fields be '?' (no specific value) because the semantics of specifying both is ambiguous and not supported. The parser checks: if day-of-month is specified AND day-of-week is specified, it throws. The '?' character tells Quartz to ignore that field.

Source

Thrown at jeecg-boot/jeecg-server-cloud/jeecg-visual/jeecg-cloud-xxljob/src/main/java/com/xxl/job/admin/business/scheduler/cron/CronExpression.java:524

            if (exprOn <= DAY_OF_WEEK) {
                throw new ParseException("Unexpected end of expression.",
                        expression.length());
            }

            if (exprOn <= YEAR) {
                storeExpressionVals(0, "*", YEAR);
            }

            TreeSet<Integer> dow = getSet(DAY_OF_WEEK);
            TreeSet<Integer> dom = getSet(DAY_OF_MONTH);

            // Copying the logic from the UnsupportedOperationException below
            boolean dayOfMSpec = !dom.contains(NO_SPEC);
            boolean dayOfWSpec = !dow.contains(NO_SPEC);

            if (!dayOfMSpec || dayOfWSpec) {
                if (!dayOfWSpec || dayOfMSpec) {
                    throw new ParseException(
                            "Support for specifying both a day-of-week AND a day-of-month parameter is not implemented.", 0);
                }
            }
        } catch (ParseException pe) {
            throw pe;
        } catch (Exception e) {
            throw new ParseException("Illegal cron expression format ("
                    + e + ")", 0);
        }
    }

    protected int storeExpressionVals(int pos, String s, int type)
            throws ParseException {

        int incr = 0;
        int i = skipWhiteSpace(pos, s);
        if (i >= s.length()) {
            return i;

View on GitHub (pinned to 96fb33f5ec)

Solutions

  1. If you want to trigger on a specific day of the month regardless of weekday, use '?' for day-of-week: '0 0 12 15 * ?'.
  2. If you want to trigger on specific weekdays regardless of the date, use '?' for day-of-month: '0 0 12 ? * MON-FRI'.
  3. If you need both conditions (e.g., '15th of month AND it's a Monday'), use two separate triggers and filter in your job logic, or use a single trigger with broader scope and check the condition in the job.
  4. Remember: '*' in day-of-month or day-of-week counts as 'specified' — you must use '?' to mark a field as 'no value'.

Example fix

// before: both dom and dow specified — invalid
String cron = "0 0 12 15 * MON";
CronExpression expr = new CronExpression(cron);

// after: use '?' for the field you don't care about
// Option 1: trigger on the 15th of every month (any weekday)
String cron1 = "0 0 12 15 * ?";
// Option 2: trigger every Monday (any date)
String cron2 = "0 0 12 ? * MON";
CronExpression expr = new CronExpression(cron1);
Defensive patterns

Strategy: validation

Validate before calling

// Pre-validate that day-of-month and day-of-week are not both specified
public void validateDomDowExclusion(String expression) {
    String[] fields = expression.trim().split("\\s+");
    if (fields.length < 6) return; // Let field-count validation handle this
    String dom = fields[3]; // day-of-month
    String dow = fields[5]; // day-of-week
    boolean domSpecified = !"?".equals(dom);
    boolean dowSpecified = !"?".equals(dow);
    if (domSpecified && dowSpecified) {
        throw new IllegalArgumentException(
            "Cannot specify both day-of-month ('" + dom + "') and day-of-week ('" + dow +
            "'). Use '?' for the field you want to ignore.");
    }
}

Type guard

// Check if at least one of dom/dow is '?'
public boolean hasValidDomDowExclusion(String expression) {
    String[] fields = expression.trim().split("\\s+");
    if (fields.length < 6) return false;
    String dom = fields[3];
    String dow = fields[5];
    return "?".equals(dom) || "?".equals(dow);
}

Try / catch

try {
    CronExpression cron = new CronExpression(expression);
} catch (ParseException e) {
    if (e.getMessage().contains("day-of-week AND a day-of-month")) {
        throw new IllegalArgumentException(
            "Quartz does not allow specifying both day-of-month and day-of-week. " +
            "Use '?' for the field you want to ignore. Expression: " + expression, e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Cron expression like '0 0 12 15 * 1' where both day-of-month (15) and day-of-week (1/Monday) are specified. Expression like '0 0 12 * * 1-5' is fine (dom is '*'), but '0 0 12 1-31 * 1-5' is not (both dom and dow have explicit ranges, and neither is '?'). Expression like '0 0 12 15 * MON' triggers the error.

Common situations: Users familiar with standard Unix cron (which allows specifying both dom and dow as an OR condition) transitioning to Quartz cron (which does not). Forgetting to use '?' for the unused day field. Copying expressions from Unix cron documentation directly into a Quartz-based scheduler like XXL-Job.

Related errors


AI-assisted analysis of jeecgboot/JeecgBoot@96fb33f5ec (2026-08-14). Data as JSON: /api/errors/dabeef522441b456. Report an issue: GitHub.