{"record":{"id":"e66497feae3dea32","repo":"alibaba/spring-cloud-alibaba","slug":"unexpected-end-of-string","errorCode":null,"errorMessage":"Unexpected end of string.","messagePattern":"Unexpected end of string\\.","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":426,"sourceCode":"\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)) {\n\t\t\t\t\tthrow new ParseException(\"Increment > 60 : \" + incr, i);\n\t\t\t\t}\n\t\t\t\telse if (incr > 23 && (type == HOUR)) {\n\t\t\t\t\tthrow new ParseException(\"Increment > 24 : \" + incr, i);\n\t\t\t\t}\n\t\t\t\telse if (incr > 31 && (type == DAY_OF_MONTH)) {\n\t\t\t\t\tthrow new ParseException(\"Increment > 31 : \" + incr, i);\n\t\t\t\t}\n\t\t\t\telse if (incr > 7 && (type == DAY_OF_WEEK)) {","sourceCodeStart":408,"sourceCodeEnd":444,"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#L408-L444","documentation":"Thrown after a '*' (or leading '/') is consumed and a following '/' is found, but advancing past the '/' runs off the end of the token — i.e. there is no increment value after the slash at all (guard at CronExpression.java:425-426). This differs from error 80, which fires on a leading '/' followed by whitespace; error 81 fires when '*' was already consumed and the trailing '/' has no digit. It is a checked ParseException from the constructor.","triggerScenarios":"Constructing `new CronExpression(\"0 0 0 ? * */\")` where the day-of-week (last) field is '*/' with nothing after the slash. Any field token ending in exactly '*/' with no digits triggers the `i >= s.length()` check at line 425.","commonSituations":"Truncation of a cron string (e.g. a config value trimmed to `\"0 0 0 ? * */\"`), or a templated cron where `${step}` was empty producing `*/`. Also from copy-paste where the trailing increment was dropped.","solutions":["Add the missing step integer after the trailing '/', e.g. '*/' -> '*/2'.","Audit config templates/property placeholders so an empty `${step}` cannot yield a bare '*/'.","Use '*' alone if you want 'every' rather than a step.","Validate the cron string with the helper below before constructing."],"exampleFix":"// before\nnew CronExpression(\"0 0 0 ? * */\");\n// after\nnew CronExpression(\"0 0 0 ? * */2\"); // every 2 days-of-week","handlingStrategy":"try-catch","validationCode":"// Reject tokens that end with a bare '*/'.\nstatic boolean noTrailingBareSlash(String cron) {\n    if (cron == null) return true;\n    for (String f : cron.trim().split(\"\\\\s+\")) {\n        if (f.endsWith(\"*/\") || f.endsWith(\"/\")) 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":["Never leave '*/' without a following digit.","Default empty step placeholders to a concrete value (e.g. ${step:1}).","Unit-test templated cron strings for all placeholder combinations."],"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"}