xuxueli/xxl-job · error · ParseException
Minute and Second values must be between 0 and 59
Error message
Minute and Second values must be between 0 and 59
What it means
In addToSet, for the seconds or minutes field (type SECOND or MINUTE), the value must be between 0 and 59 inclusive, and the range end must also be <= 59. The only exception is ALL_SPEC_INT (99), which represents '*'. This error fires for any out-of-range value or range endpoint.
Source
Thrown at xxl-job-admin/src/main/java/com/xxl/job/admin/business/scheduler/cron/CronExpression.java:988
return i;
}
protected int findNextWhiteSpace(int i, String s) {
for (; i < s.length() && (s.charAt(i) != ' ' || s.charAt(i) != '\t'); i++) {
}
return i;
}
protected void addToSet(int val, int end, int incr, int type)
throws ParseException {
TreeSet<Integer> set = getSet(type);
if (type == SECOND || type == MINUTE) {
if ((val < 0 || val > 59 || end > 59) && (val != ALL_SPEC_INT)) {
throw new ParseException(
"Minute and Second values must be between 0 and 59",
-1);
}
} else if (type == HOUR) {
if ((val < 0 || val > 23 || end > 23) && (val != ALL_SPEC_INT)) {
throw new ParseException(
"Hour values must be between 0 and 23", -1);
}
} else if (type == DAY_OF_MONTH) {
if ((val < 1 || val > 31 || end > 31) && (val != ALL_SPEC_INT)
&& (val != NO_SPEC_INT)) {
throw new ParseException(
"Day of month values must be between 1 and 31", -1);
}
} else if (type == MONTH) {
if ((val < 1 || val > 12 || end > 12) && (val != ALL_SPEC_INT)) {
throw new ParseException(
"Month values must be between 1 and 12", -1);View on GitHub (pinned to e74c784f68)
Solutions
- Clamp second and minute values to 0-59 before constructing the cron string.
- Use '*' if you mean 'every second/minute' rather than a large number.
- Validate the cron expression with a dedicated validator before passing it to the CronExpression constructor.
Example fix
// before "60 * * * * ?" // after "0/30 * * * * ?"
Defensive patterns
Strategy: validation
Validate before calling
// Validate seconds (field 0) and minutes (field 1) values are 0-59
String[] parts = cron.trim().split("\\s+");
for (int idx : new int[]{0, 1}) {
if (parts.length > idx && !parts[idx].equals("*") && !parts[idx].equals("?")) {
String numStr = parts[idx].replaceAll("[^0-9].*", "");
if (!numStr.isEmpty()) {
int val = Integer.parseInt(numStr);
if (val < 0 || val > 59) throw new IllegalArgumentException("Second/minute value must be 0-59: " + val);
}
}
} Type guard
boolean isValidSecondMinuteValue(String field) {
if ("*".equals(field) || "?".equals(field)) return true;
try {
int val = Integer.parseInt(field.replaceAll("[^0-9].*", ""));
return val >= 0 && val <= 59;
} catch (NumberFormatException e) { return false; } Try / catch
try {
new CronExpression(cron);
} catch (ParseException e) {
if (e.getMessage().contains("Minute and Second values must be between 0 and 59")) {
// clamp the value to 0-59 and retry
}
} Prevention
- Seconds and minutes are 0-indexed (0-59), not 1-indexed.
- Clamp second/minute values to 0-59 before building the cron expression.
- Use '*' for 'every second/minute' rather than entering a large number.
When it happens
Trigger: A cron expression like '60 * * * * ?' (seconds=60), '0-60 * * * * ?' (range end 60), or '0 70 * * * ?' (minutes=70). The check at line 987 tests (val < 0 || val > 59 || end > 59) && val != ALL_SPEC_INT.
Common situations: Off-by-one errors when generating second/minute values, using 1-indexed logic on a 0-indexed field, or a UI that allows entering 60 as a maximum.
Related errors
AI-assisted analysis of xuxueli/xxl-job@e74c784f68 (2026-08-14).
Data as JSON: /api/errors/9795c4699a3fda9f.
Report an issue: GitHub.