flowable/flowable-engine · error · ParseException

'#' option is not valid here. (pos=

Error message

'#' option is not valid here. (pos=

What it means

The cron expression parser in Flowable's CronExpression (a Quartz-derived parser) found a '#' character, which is only allowed in the day-of-week field to mean 'the nth weekday of the month' (e.g. 'FRI#3'). A '#' appearing in any other field (second, minute, hour, day-of-month, month, year) is syntactically invalid there, so a ParseException is thrown during storeExpressionVals/checkNext. This happens at expression-parse time, before any scheduling occurs.

Source

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

            if (type == DAY_OF_MONTH) {
                nearestWeekday = true;
            } else {
                throw new ParseException("'W' option is not valid here. (pos=" + i + ")", i);
            }
            if (val > 31) {
                throw new ParseException(
                        "The 'W' option does not make sense with values larger than 31 (max number of days in a month)",
                        i);
            }
            TreeSet<Integer> set = getSet(type);
            set.add(val);
            i++;
            return i;
        }

        if (c == '#') {
            if (type != DAY_OF_WEEK) {
                throw new ParseException("'#' option is not valid here. (pos=" + i + ")", i);
            }
            i++;
            try {
                nthdayOfWeek = Integer.parseInt(s.substring(i));
                if (nthdayOfWeek < 1 || nthdayOfWeek > 5) {
                    throw new Exception();
                }
            } catch (Exception e) {
                throw new ParseException("A numeric value between 1 and 5 must follow the '#' option", i);
            }

            TreeSet<Integer> set = getSet(type);
            set.add(val);
            i++;
            return i;
        }

        if (c == '-') {

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Move the '#' nth-weekday clause into the day-of-week field, e.g. '0 0 0 ? * FRI#3' instead of placing it elsewhere
  2. Remove the '#' if it was intended as a comment — cron strings here do not support inline comments; place comments outside the expression
  3. Validate the cron expression with CronExpression.isValidExpression(expr) before feeding it to the engine to fail fast with a clearer message
  4. Count the fields: a Quartz-style cron has 6 or 7 fields (second minute hour day-of-month month [day-of-week] [year]); ensure each token sits in the right position

Example fix

// before
CronExpression cron = new CronExpression("0 0 15#2 * *"); // '#' in hour field
// after
CronExpression cron = new CronExpression("0 0 0 ? * FRI#2"); // nth-Friday in day-of-week field
Defensive patterns

Strategy: validation

Validate before calling

String expr = "0 0 0 ? * FRI#2";
String dow = expr.split("\\s+")[5];
if (expr.contains("#") && !dow.contains("#")) {
    throw new IllegalArgumentException("'#' may only appear in the day-of-week field: " + expr);
}
if (!org.flowable.common.engine.impl.calendar.CronExpression.isValidExpression(expr)) {
    throw new IllegalArgumentException("Invalid cron expression: " + expr);
}

Try / catch

try {
    CronExpression cron = new CronExpression(expr);
} catch (ParseException e) {
    log.error("Bad cron expression at position {}: {}", e.getErrorOffset(), e.getMessage());
    throw new ConfigurationException("Invalid cron expression: " + expr, e);
}

Prevention

When it happens

Trigger: Calling new CronExpression(expr) or passing a cron string to Flowable configuration (e.g. process/timer definitions) where a '#' appears outside the day-of-week field — e.g. '0 0 15#1 * *' or a '#' accidentally placed in the day-of-month field.

Common situations: Copy-pasted cron expressions from systems with different cron dialects (some allow different token positions); hand-edited expressions where '#' was meant for day-of-week but shifted into day-of-month; typo or leftover shell-comment '#' inside the expression (classic crontab files allow # comments, but an inline comment within the 6-7 field cron string is invalid).

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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