xuxueli/xxl-job · error · ParseException

Unexpected end of string.

Error message

Unexpected end of string.

What it means

Thrown when a '*' is followed by '/' and then the string ends immediately — the parser increments past the '/' and finds no increment value at all. This is the 'dangling slash' case distinct from error 21 because here the '*' was consumed first and the code advanced i past '/' before discovering the end of string.

Source

Thrown at xxl-job-admin/src/main/java/com/xxl/job/admin/business/scheduler/cron/CronExpression.java:651

            return i;
        }

        if (c == '*' || c == '/') {
            if (c == '*' && (i + 1) >= s.length()) {
                addToSet(ALL_SPEC_INT, -1, incr, type);
                return i + 1;
            } else if (c == '/'
                    && ((i + 1) >= s.length() || s.charAt(i + 1) == ' ' || s
                    .charAt(i + 1) == '\t')) {
                throw new ParseException("'/' must be followed by an integer.", i);
            } else if (c == '*') {
                i++;
            }
            c = s.charAt(i);
            if (c == '/') { // is an increment specified?
                i++;
                if (i >= s.length()) {
                    throw new ParseException("Unexpected end of string.", i);
                }

                incr = getNumericValue(s, i);

                i++;
                if (incr > 10) {
                    i++;
                }
                checkIncrementRange(incr, type, i);
            } else {
                incr = 1;
            }

            addToSet(ALL_SPEC_INT, -1, incr, type);
            return i;
        } else if (c == 'L') {

            if(type < DAY_OF_MONTH)

View on GitHub (pinned to e74c784f68)

Solutions

  1. Append a valid increment integer after '*/' (e.g., '*/5').
  2. Strip the trailing '/' if the increment is not needed.
  3. Use a pre-submit cron syntax validator to catch incomplete step expressions.

Example fix

// before
"0 0 0 */ * * ?"
// after
"0 0 0 */5 * * ?"
Defensive patterns

Strategy: validation

Validate before calling

// Reject dangling '*/' at the end of any field
for (String field : cron.trim().split("\\s+")) {
    if (field.endsWith("*/") || field.endsWith("/")) {
        throw new IllegalArgumentException("Incomplete step expression (trailing '/'): " + field);
    }
}

Type guard

boolean isCompleteStep(String field) {
    return !field.endsWith("/");

Try / catch

try {
    new CronExpression(cron);
} catch (ParseException e) {
    if (e.getMessage().contains("Unexpected end of string")) {
        // append a default step or ask the user to complete it
    }
}

Prevention

When it happens

Trigger: A cron field exactly equal to '*/' with no characters after the '/'. The code at line 648 sets c='/', increments i past it, then checks i >= s.length() and throws.

Common situations: String truncation during input processing, a cron builder that concatenates '*' and '/' conditionally but omits the step value, or manual editing that leaves an incomplete expression.

Related errors


AI-assisted analysis of xuxueli/xxl-job@e74c784f68 (2026-08-14). Data as JSON: /api/errors/983f0a660dcb365a. Report an issue: GitHub.