alibaba/spring-cloud-alibaba · error · ParseException
'?' can only be specfied for Day-of-Month -OR- Day-of-Week.
Error message
'?' can only be specfied for Day-of-Month -OR- Day-of-Week.
What it means
Thrown while parsing the DAY_OF_WEEK '?' token when the DAY_OF_MONTH field was also set to '?' (NO_SPEC). Quartz requires exactly one of the two day fields to be '?' and the other to carry a value; setting '?' for both is illegal. ParseException message: "'?' can only be specified for Day-of-Month -OR- Day-of-Week."
Source
Thrown at spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-schedulerx/src/main/java/com/alibaba/cloud/scheduling/schedulerx/util/CronExpression.java:399
return (i + 3);
}
if (c == '?') {
i++;
if ((i + 1) < s.length()
&& (s.charAt(i) != ' ' && s.charAt(i + 1) != '\t')) {
throw new ParseException("Illegal character after '?': "
+ s.charAt(i), i);
}
if (type != DAY_OF_WEEK && type != DAY_OF_MONTH) {
throw new ParseException(
"'?' can only be specfied for Day-of-Month or Day-of-Week.",
i);
}
if (type == DAY_OF_WEEK && !lastdayOfMonth) {
final int val = daysOfMonth.last();
if (val == NO_SPEC_INT) {
throw new ParseException(
"'?' can only be specfied for Day-of-Month -OR- Day-of-Week.",
i);
}
}
addToSet(NO_SPEC_INT, -1, 0, type);
return i;
}
if (c == '*' || c == '/') {
if (c == '*' && (i + 1) >= s.length()) {
addToSet(ALL_SPEC_INT, -1, incr, type);
return i + 1;
}
else if (c == '/'
&& ((i + 1) >= s.length() || s.charAt(i + 1) == ' ' || s
.charAt(i + 1) == '\t')) {
throw new ParseException("'/' must be followed by an integer.", i);View on GitHub (pinned to 115d590110)
Solutions
- Set exactly one day field to a real value and the other to '?': e.g. '0 0 0 * * ?' (every day via DOM='*') or '0 0 0 ? * *' (every day via DOW='*').
- If you want 'every day', use '*' for day-of-month and '?' for day-of-week.
- Validate at config load.
Example fix
# before ('?' in both day fields)
0 0 0 ? * ?
# after (every day: DOM='*', DOW='?')
0 0 0 * * ? Defensive patterns
Strategy: try-catch
Validate before calling
static String validateCron(String cron) throws ParseException {
new com.alibaba.cloud.scheduling.schedulerx.util.CronExpression(cron);
return cron;
} Type guard
// exactly one of DOM(3)/DOW(5) must be '?'
static boolean exactlyOneDayFieldIsQ(String[] f) {
if (f.length < 6) return false;
boolean a = "?".equals(f[3]);
boolean b = "?".equals(f[5]);
return a ^ b;
} Try / catch
try {
new CronExpression(cron);
} catch (ParseException e) {
// "'?' can only be specified for Day-of-Month -OR- Day-of-Week."
log.error("Use '?' for only ONE day field in cron '{}'", cron);
} Prevention
- Rule: one day field gets a value, the other gets '?' — never both '?'.
- For 'every day', prefer '* * ?' over '? * ?'.
When it happens
Trigger: An expression with '?' in both day positions, e.g. '0 0 0 ? * ?'. When processing the DOW '?' the parser reads daysOfMonth.last(); if that value is NO_SPEC_INT (98, meaning DOM was also '?') it throws at CronExpression.java:397-401.
Common situations: Using '? * ?' pattern thinking '?' means 'ignore both'; converting from a dialect that allows '?' in both; a template that defaults both day fields to '?'.
Related errors
- Support for specifying 'L' and 'LW' with other days of the m
- Support for specifying 'L' with other days of the week is no
- Support for specifying multiple "nth" days is not implemente
- Unexpected end of expression.
- Support for specifying both a day-of-week AND a day-of-month
AI-assisted analysis of alibaba/spring-cloud-alibaba@115d590110 (2026-08-14).
Data as JSON: /api/errors/6cc68ac6fe1b0065.
Report an issue: GitHub.