xuxueli/xxl-job · error · ParseException

Unexpected character: {}

Error message

Unexpected character: {}

What it means

This is the catch-all for any character in a cron field that the parser does not recognize. The parser handles '?', '*', '/', 'L', and digits 0-9; any other character (e.g., letters other than 'L', symbols like '&', '%', '!') triggers this error.

Source

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

            }
            return i;
        } else if (c >= '0' && c <= '9') {
            int val = Integer.parseInt(String.valueOf(c));
            i++;
            if (i >= s.length()) {
                addToSet(val, -1, -1, type);
            } else {
                c = s.charAt(i);
                if (c >= '0' && c <= '9') {
                    ValueSet vs = getValue(val, s, i);
                    val = vs.value;
                    i = vs.pos;
                }
                i = checkNext(i, s, val, type);
                return i;
            }
        } else {
            throw new ParseException("Unexpected character: " + c, i);
        }

        return i;
    }

    private void checkIncrementRange(int incr, int type, int idxPos) throws ParseException {
        if (incr > 59 && (type == SECOND || type == MINUTE)) {
            throw new ParseException("Increment >= 60 : " + incr, idxPos);
        } else if (incr > 23 && (type == HOUR)) {
            throw new ParseException("Increment >= 24 : " + incr, idxPos);
        } else if (incr > 31 && (type == DAY_OF_MONTH)) {
            throw new ParseException("Increment >= 31 : " + incr, idxPos);
        } else if (incr > 7 && (type == DAY_OF_WEEK)) {
            throw new ParseException("Increment >= 7 : " + incr, idxPos);
        } else if (incr > 12 && (type == MONTH)) {
            throw new ParseException("Increment >= 12 : " + incr, idxPos);
        }
    }

View on GitHub (pinned to e74c784f68)

Solutions

  1. Inspect the cron string for stray or non-ASCII characters and remove them.
  2. Replace named-day or macro syntax with Quartz-compatible numeric cron tokens.
  3. Run the raw string through a character-level check to detect non-printable characters before parsing.

Example fix

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

Strategy: validation

Validate before calling

// Only allow known cron characters in each field
String allowed = "0123456789*/-?LW#,";
for (char ch : cron.toCharArray()) {
    if (!Character.isWhitespace(ch) && allowed.indexOf(ch) == -1) {
        throw new IllegalArgumentException("Invalid cron character: '" + ch + "'");
    }
}

Type guard

boolean hasOnlyCronChars(String cron) {
    for (char c : cron.toCharArray()) {
        if (!Character.isWhitespace(c) && "0123456789*/-?LW#,".indexOf(c) == -1) return false;
    }
    return true;

Try / catch

try {
    new CronExpression(sanitizedCron);
} catch (ParseException e) {
    if (e.getMessage().contains("Unexpected character")) {
        // strip non-cron characters and re-validate
    }
}

Prevention

When it happens

Trigger: A cron field containing an invalid character such as '0 & * * * ?' (ampersand in seconds), 'x * * * * ?', or any stray symbol. The else branch at line 720 fires when none of the preceding character checks match.

Common situations: Encoding issues, invisible characters pasted from a rich-text source, or using a non-Quartz cron dialect that uses different syntax (e.g., '@daily' macro or named days like 'MON' without proper field context).

Related errors


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