{"record":{"id":"df451e1436a6de62","repo":"jeecgboot/JeecgBoot","slug":"minute-and-second-values-must-be-between-0-and-59","errorCode":null,"errorMessage":"Minute and Second values must be between 0 and 59","messagePattern":"Minute and Second values must be between 0 and 59","errorType":"validation","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":988,"sourceCode":"\n        return i;\n    }\n\n    protected int findNextWhiteSpace(int i, String s) {\n        for (; i < s.length() && (s.charAt(i) != ' ' || s.charAt(i) != '\\t'); i++) {\n        }\n\n        return i;\n    }\n\n    protected void addToSet(int val, int end, int incr, int type)\n            throws ParseException {\n\n        TreeSet<Integer> set = getSet(type);\n\n        if (type == SECOND || type == MINUTE) {\n            if ((val < 0 || val > 59 || end > 59) && (val != ALL_SPEC_INT)) {\n                throw new ParseException(\n                        \"Minute and Second values must be between 0 and 59\",\n                        -1);\n            }\n        } else if (type == HOUR) {\n            if ((val < 0 || val > 23 || end > 23) && (val != ALL_SPEC_INT)) {\n                throw new ParseException(\n                        \"Hour values must be between 0 and 23\", -1);\n            }\n        } else if (type == DAY_OF_MONTH) {\n            if ((val < 1 || val > 31 || end > 31) && (val != ALL_SPEC_INT)\n                    && (val != NO_SPEC_INT)) {\n                throw new ParseException(\n                        \"Day of month values must be between 1 and 31\", -1);\n            }\n        } else if (type == MONTH) {\n            if ((val < 1 || val > 12 || end > 12) && (val != ALL_SPEC_INT)) {\n                throw new ParseException(\n                        \"Month values must be between 1 and 12\", -1);","sourceCodeStart":970,"sourceCodeEnd":1006,"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#L970-L1006","documentation":"Thrown by addToSet when a value (or range end) for the SECOND or MINUTE field is less than 0 or greater than 59, unless the value is ALL_SPEC_INT (the internal sentinel for '*'). This guards the final value that gets stored in the TreeSet after all parsing and range resolution, so it catches both raw values and computed range endpoints.","triggerScenarios":"A cron expression with a seconds or minutes field containing a value like 60, 99, -1, or a range like 0–70 — e.g., seconds field '60', minutes field '45,75', or range '10-65'. Also triggered if a step computation overflows, though the range check in setAddition usually catches that earlier.","commonSituations":"Developer uses 60 as a minute/second value (should be 0); off-by-one in range bounds; dynamic value injection without bounds checking; confusion between 0-based and 1-based fields.","solutions":["Ensure all second and minute values are integers from 0 to 59.","Check range endpoints: '0-59' is valid, '0-60' is not.","Validate dynamic cron components against field bounds before constructing the expression."],"exampleFix":"// before\nString cron = \"60 * * * * ?\";  // 60 is invalid for seconds\n// after\nString cron = \"0/30 * * * * ?\";  // every 30 seconds","handlingStrategy":"validation","validationCode":"// Validate seconds/minutes field values are 0-59\nvoid validateSecondOrMinute(String field) {\n    for (String token : field.split(\",\")) {\n        token = token.split(\"[/\\\\-]\")[0]; // take base value\n        if (!token.equals(\"*\") && !token.equals(\"?\")) {\n            int val = Integer.parseInt(token);\n            if (val < 0 || val > 59) throw new IllegalArgumentException(\"Value must be 0-59: \" + val);\n        }\n    }\n}","typeGuard":"boolean isValidSecondOrMinute(String field) {\n    for (String token : field.split(\",\")) {\n        if (token.equals(\"*\") || token.equals(\"?\")) continue;\n        try {\n            for (String part : token.split(\"[/\\\\-]\")) {\n                int val = Integer.parseInt(part);\n                if (val < 0 || val > 59) return false;\n            }\n        } catch (NumberFormatException e) { return false; }\n    }\n    return true;\n}","tryCatchPattern":"try {\n    CronExpression cron = new CronExpression(expr);\n} catch (ParseException e) {\n    if (e.getMessage().contains(\"Minute and Second values must be between 0 and 59\")) {\n        // fix the seconds or minutes field value\n    }\n    throw e;\n}","preventionTips":["Keep second and minute values in the 0–59 range.","Use 0 for the start, not 60 or 1 for the beginning of the minute.","Bounds-check dynamically generated field values."],"tags":["cron","validation","scheduling","xxljob","parse"],"backgroundTag":null,"analyzedSha":"96fb33f5ec68516da0b0147da06b2eb0419e063a","analyzedAt":"2026-08-14T00:04:16.786Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}