flowable/flowable-engine · error · java.text.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
Flowable's CronExpression validates each parsed field against its legal numeric range. When a set of second or minute values is built (in addToSet, called from storeExpressionVals while parsing), any value below 0 or above 59 (including an end-of-range value > 59) is rejected — except the internal ALL_SPEC sentinel — with this ParseException. It fires at expression-parse time with position -1 because the offending field is only known as a set at that point.
Source
Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/calendar/CronExpression.java:977
}
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);
}
} else if (type == DAY_OF_WEEK) {
if ((val == 0 || val > 7 || end > 7) && (val != ALL_SPEC_INT) && (val != NO_SPEC_INT)) {
throw new ParseException("Day-of-Week values must be between 1 and 7", -1);
}
}View on GitHub (pinned to d6d39ce1c6)
Solutions
- Keep seconds and minutes in the range 0-59; normalize any computed value with Math.floorMod(value, 60) before building the expression
- If the intent was an interval, use the increment form instead of an out-of-range value, e.g. '0/90' is still invalid — instead use '0 0/2 * * * ?' style fields or restructure the schedule
- Convert duration-style inputs (milliseconds) to a proper schedule before rendering a cron expression; never paste a duration number into a seconds field
- Pre-validate with CronExpression.isValidExpression(expr) and surface a clear message to users configuring timers
Example fix
// before String cron = "0 " + intervalSeconds + " * * * ?"; // intervalSeconds could be 90 // after int normalized = Math.floorMod(intervalSeconds, 60); String cron = "0 " + normalized + " * * * ?"; // always 0-59
Defensive patterns
Strategy: validation
Validate before calling
int normalize60(int v) { return Math.floorMod(v, 60); }
// before building the expression
if (seconds < 0 || seconds > 59 || minutes < 0 || minutes > 59) {
throw new IllegalArgumentException("Seconds/minutes must be 0-59");
}
String expr = seconds + " " + minutes + " " + hours + " * * ?";
if (!CronExpression.isValidExpression(expr)) {
throw new IllegalArgumentException("Invalid cron expression: " + expr);
} Type guard
boolean isValidSecondOrMinute(int v) {
return v >= 0 && v <= 59;
} Try / catch
try {
CronExpression cron = new CronExpression(expr);
} catch (ParseException e) {
throw new ConfigurationException("Cron seconds/minutes must be 0-59: " + expr, e);
} Prevention
- Normalize computed time components with Math.floorMod(v, 60) before string-building
- Never place duration/millisecond values directly into seconds or minutes fields
- Convert Unix 5-field crons to the 6/7-field Quartz format rather than pasting them directly
- Validate user-configured expressions with isValidExpression and reject them at input time
When it happens
Trigger: new CronExpression(expr) where the seconds or minutes field contains a number > 59 or negative — e.g. '60 * * * * ?' (60 seconds), '0 75 * * * ?' (75 minutes), or computed values produced by arithmetic in generated expressions.
Common situations: Confusing seconds with milliseconds in generated timers (60000 ms written into the seconds field); copying Unix cron (5 fields, minute first, some allow 60 in edge tooling) into the 6/7-field Quartz format incorrectly; building expressions programmatically with offsets that overflow the 0-59 range instead of being normalized modulo 60.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- '#' option is not valid here. (pos=
- Unexpected character '<c>' after '/'
- Hour values must be between 0 and 23
- Day of month values must be between 1 and 31
- Month values must be between 1 and 12
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/dbedf8666b1894e7.
Report an issue: GitHub.