flowable/flowable-engine · error · IllegalStateException

The [ ] must resolve to an Number or a String that can be…

Error message

The [<attribute>] must resolve to an Number or a String that can be parsed as a Long. Resolved to [<class>] for [<value>]

What it means

resolveExpressionAsLong resolves an attribute expression for a Long-typed setting and accepts null, String-parseable-as-Long, or Number. Any other resolved type causes IllegalStateException. It is called by the retry backoff delay and max configuration, so a bad expression type in backoff settings triggers it.

Solutions

  1. Ensure the delay/max expression resolves to a whole number or numeric String (e.g. 1000 or "1000").
  2. Remove units/decimals from the configured value; use milliseconds as a plain integer.
  3. Fix the backing property type to Long/long if it resolves from a bean field.
  4. If a Duration is desired, convert to millis in the expression.

Example fix

// before
flowable:
  kafka:
    retry:
      delay: 1.5s   # resolves to a Duration, not Long

// after
flowable:
  kafka:
    retry:
      delay: 1500
Defensive patterns

Strategy: type-guard

Validate before calling

Object v = resolveExpression(value);
if (v != null && !(v instanceof Number) && !(v instanceof String)) throw new IllegalArgumentException(attribute + " must be long-like");

Type guard

boolean isLongLike(Object v) { return v == null || v instanceof Number || (v instanceof String s && s.matches("-?\\d+")); }

Try / catch

try { ... } catch (IllegalStateException e) { if (e.getMessage().contains("parsed as a Long")) { log.error("Backoff delay/max not a Long: {}", e.getMessage()); } else throw e; }

Prevention

When it happens

Trigger: The delay or max attribute of a retry/backoff configuration in the Kafka channel model resolves (via expression/placeholder) to a non-Long, non-String object (e.g. Double or a bean) when the listener endpoint is created.

Common situations: YAML value with decimal point (1.5) where Long expected is fine as String? no—actually a resolved Double; property bound to a Duration object; placeholder pointing to wrong key returning a map/list.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable-event-registry-spring/src/main/java/org/flowable/eventregistry/spring/kafka/KafkaChannelDefinitionProcessor.java:477

        } else if (resolved instanceof Number) {
            result = ((Number) resolved).intValue();
        } else if (resolved != null) {
            throw new IllegalStateException(
                "The [" + attribute + "] must resolve to an Number or a String that can be parsed as an Integer. "
                    + "Resolved to [" + resolved.getClass() + "] for [" + value + "]");
        }
        return result;
    }

    protected Long resolveExpressionAsLong(String value, String attribute) {
        Object resolved = resolveExpression(value);
        Long result = null;
        if (resolved instanceof String) {
            result = Long.parseLong((String) resolved);
        } else if (resolved instanceof Number) {
            result = ((Number) resolved).longValue();
        } else if (resolved != null) {
            throw new IllegalStateException(
                    "The [" + attribute + "] must resolve to an Number or a String that can be parsed as a Long. "
                            + "Resolved to [" + resolved.getClass() + "] for [" + value + "]");
        }
        return result;
    }

    protected Double resolveExpressionAsDouble(String value, String attribute) {
        Object resolved = resolveExpression(value);
        Double result = null;
        if (resolved instanceof String) {
            result = Double.parseDouble((String) resolved);
        } else if (resolved instanceof Number) {
            result = ((Number) resolved).doubleValue();
        } else if (resolved != null) {
            throw new IllegalStateException(
                    "The [" + attribute + "] must resolve to an Number or a String that can be parsed as a Double. "
                            + "Resolved to [" + resolved.getClass() + "] for [" + value + "]");
        }

View on GitHub (pinned to d6d39ce1c6)