{"record":{"id":"07da3f02f9fcd215","repo":"alibaba/spring-cloud-alibaba","slug":"must-be-followed-by-an-integer","errorCode":null,"errorMessage":"'/' must be followed by an integer.","messagePattern":"'/' must be followed by an integer\\.","errorType":"exception","errorClass":"ParseException","httpStatus":null,"severity":"error","filePath":"spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-schedulerx/src/main/java/com/alibaba/cloud/scheduling/schedulerx/util/CronExpression.java","lineNumber":417,"sourceCode":"\t\t\t\t\tthrow new ParseException(\n\t\t\t\t\t\t\t\"'?' can only be specfied for Day-of-Month -OR- Day-of-Week.\",\n\t\t\t\t\t\t\ti);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\taddToSet(NO_SPEC_INT, -1, 0, type);\n\t\t\treturn i;\n\t\t}\n\n\t\tif (c == '*' || c == '/') {\n\t\t\tif (c == '*' && (i + 1) >= s.length()) {\n\t\t\t\taddToSet(ALL_SPEC_INT, -1, incr, type);\n\t\t\t\treturn i + 1;\n\t\t\t}\n\t\t\telse if (c == '/'\n\t\t\t\t\t&& ((i + 1) >= s.length() || s.charAt(i + 1) == ' ' || s\n\t\t\t\t\t.charAt(i + 1) == '\\t')) {\n\t\t\t\tthrow new ParseException(\"'/' must be followed by an integer.\", i);\n\t\t\t}\n\t\t\telse if (c == '*') {\n\t\t\t\ti++;\n\t\t\t}\n\t\t\tc = s.charAt(i);\n\t\t\tif (c == '/') { // is an increment specified?\n\t\t\t\ti++;\n\t\t\t\tif (i >= s.length()) {\n\t\t\t\t\tthrow new ParseException(\"Unexpected end of string.\", i);\n\t\t\t\t}\n\n\t\t\t\tincr = getNumericValue(s, i);\n\n\t\t\t\ti++;\n\t\t\t\tif (incr > 10) {\n\t\t\t\t\ti++;\n\t\t\t\t}\n\t\t\t\tif (incr > 59 && (type == SECOND || type == MINUTE)) {","sourceCodeStart":399,"sourceCodeEnd":435,"githubUrl":"https://github.com/alibaba/spring-cloud-alibaba/blob/115d5901102009492e05d5ec18c3f79cad4077d0/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-schedulerx/src/main/java/com/alibaba/cloud/scheduling/schedulerx/util/CronExpression.java#L399-L435","documentation":"Thrown by the Quartz-style cron parser when a field token begins with '/' but the '/' is not followed by an integer increment (it is immediately at end-of-string or followed by a space/tab). The '/' character in cron means 'every N units' and always requires a numeric step value, e.g. '*/5' or '0/10'. It surfaces as a checked java.text.ParseException from the CronExpression constructor (CronExpression.java:123 -> buildExpression -> storeExpressionVals, line 417).","triggerScenarios":"Constructing `new CronExpression(\"0 / * * * ?\")` where the minute field token is a bare '/'. Also any field token equal to just '/' (e.g. day-of-month field '/'), or a token that ends right after '/' with nothing following. The guard at CronExpression.java:414-417 fires when `c == '/'` AND `i+1 >= s.length()` OR the next char is ' ' or '\\t'.","commonSituations":"A developer writes a slash step but forgets the number (e.g. types `*/` and loses the digit in editing), or builds a cron string by concatenation and leaves a trailing '/', or copies a fragment from a 5-field cron tool into this 6/7-field parser and the fields shift so a '/' lands at a field start.","solutions":["Provide a numeric increment immediately after every '/', e.g. change a bare '/' field to '*/5' or '0/15'.","Recount the cron fields: this library requires 6 fields (seconds minutes hours day-of-month month day-of-week) plus an optional year; a missing seconds field shifts everything and can put a '/' where a field starts.","If you meant 'every unit', use '*' alone instead of '/' — '/' alone is invalid.","Add a pre-flight validation pass (see validationCode) before constructing CronExpression so bad config fails fast with a clear message."],"exampleFix":"// before\nnew CronExpression(\"0 / * * * ?\");\n// after\nnew CronExpression(\"0 0/5 * * * ?\"); // every 5 minutes","handlingStrategy":"try-catch","validationCode":"// Reject a leading '/' or a '/' followed by whitespace/end before constructing.\nprivate static final Pattern VALID_FIELD_START =\n    Pattern.compile(\"^[?*L0-9]\"); // a field must start with one of these\nstatic boolean fieldStartsOk(String cron) {\n    if (cron == null) return false;\n    for (String f : cron.trim().split(\"\\\\s+\")) {\n        if (f.isEmpty() || !VALID_FIELD_START.matcher(f).find()) return false;\n        if (f.startsWith(\"/\") && (f.length() < 2 || !Character.isDigit(f.charAt(1)))) return false;\n    }\n    return true;\n}","typeGuard":null,"tryCatchPattern":"try {\n    CronExpression cron = new CronExpression(raw);\n} catch (ParseException e) {\n    throw new IllegalArgumentException(\"Invalid cron expression: \" + raw, e);\n}","preventionTips":["Always pair '/' with an explicit integer step (*/N or value/N).","Validate cron strings at config-bind time, not at first job fire.","Keep field count at 6 (seconds minutes hours dom month dow) to avoid shifting a '/' into a field start."],"tags":["cron","schedulerx","spring-cloud-alibaba","configuration","parsing","validation"],"backgroundTag":null,"analyzedSha":"115d5901102009492e05d5ec18c3f79cad4077d0","analyzedAt":"2026-08-14T04:47:13.900Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}