flowable/flowable-engine · error · java.text.ParseException

Unexpected character '<c>' after '/'

Error message

Unexpected character '<c>' after '/'

What it means

After a '/' increment operator, the parser expects either a plain integer step, a 'N/step' range form, or a name/range it can resolve (e.g. 'MON/2', 'JAN/3'). The character encountered after consuming the '/' prefix did not fit any accepted form, so this ParseException is thrown indicating the unexpected character that followed '/'.

Source

Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/calendar/CronExpression.java:852

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

        addToSet(val, end, 0, type);
        i++;
        return i;
    }

    public String getCronExpression() {
        return cronExpression;
    }

    public String getExpressionSummary() {
        StringBuilder buf = new StringBuilder();

        buf.append("seconds: ");
        buf.append(getExpressionSetSummary(seconds));
        buf.append("\n");

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Use a plain integer step after '/', e.g. '*/10' or '0/10' — 'L', '#', '?' and similar specials cannot follow '/'
  2. If a fractional or computed step is needed, round it to an integer before building the string and beware locale number formatting (use Locale.ROOT when formatting)
  3. If you meant 'last day' semantics, put 'L' in the day-of-month field directly (e.g. '0 0 0 L * ?'), not after a slash
  4. Pre-validate with CronExpression.isValidExpression(expr) to catch malformed expressions early

Example fix

// before
String cron = "0 0 0 */L * ?"; // invalid '*/L'
// after
String cron = "0 0 0 L * ?"; // last day of month
Defensive patterns

Strategy: validation

Validate before calling

String expr = "0 0 0 */10 * ?";
if (!CronExpression.isValidExpression(expr)) {
    throw new IllegalArgumentException("Invalid cron expression: " + expr);
}
// guard step rendering
if (!stepPart.matches("\\d+")) {
    throw new IllegalArgumentException("Only integer steps allowed after '/': " + stepPart);
}

Type guard

boolean isValidStepAfterSlash(String stepPart) {
    return stepPart != null && stepPart.matches("\\d+");
}

Try / catch

try {
    CronExpression cron = new CronExpression(expr);
} catch (ParseException e) {
    log.error("Unexpected character after '/' in cron {}: {}", expr, e.getMessage());
    throw new ConfigurationException("Invalid cron increment: " + expr, e);
}

Prevention

When it happens

Trigger: new CronExpression(expr) with forms like '*/X' where X is not numeric or a valid name, '0/#', '0/L' or '0/?' — i.e. '/' followed by a character that cannot start a step value or valid name token in that field.

Common situations: Combining special characters incorrectly (assuming '/' composes with 'L', 'W', '#' or '?'); typos like '0/.5'; locale-dependent decimal separators in dynamically generated steps ('0/1,5' from European number formatting); misunderstanding which special chars are legal after '/' in the Quartz dialect.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/e9c64c062e22ebc5. Report an issue: GitHub.