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 an Integer. Resolved to [<class>] for [<value>]

What it means

resolveExpressionAsInteger resolves a channel-model attribute expression (e.g. a SpEL/placeholder) and expects null, a Number, or a String parseable as Integer. If the resolved value is any other type (e.g. Boolean, Map, bean), IllegalStateException is thrown naming the attribute, resolved class, and raw value.

Solutions

  1. Point the attribute expression at a numeric value or numeric String (e.g. ${kafka.retry.maxAttempts} resolving to "3").
  2. Check the resolved bean/property type; change it to Integer/int in the configuration class.
  3. Use Integer.parseInt-safe values: ensure no units like "3s" or thousands separators in the String.
  4. Cast or convert the expression, e.g. ${...} backed by a conversion service that yields Number.

Example fix

// before (application.yml)
kafka:
  retry:
    maxAttempts: three   # resolves as non-numeric string? or a map

// after
kafka:
  retry:
    maxAttempts: 3
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 numeric");

Type guard

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

Try / catch

try { processor.createEndpointConfigurations(...); } catch (IllegalStateException e) { if (e.getMessage().contains("must resolve to")) { log.error("Bad attribute type: {}", e.getMessage()); } else throw e; }

Prevention

When it happens

Trigger: An integer attribute of the Kafka channel model (e.g. a retry-config field like maxAttempts or concurrency) is set via an expression that resolves to a non-numeric object, and resolveExpressionAsInteger (directly or via resolveRetryConfiguration) processes it.

Common situations: Placeholder points to a bean/Map instead of a property; YAML property typed as list/boolean; expression typo resolving a method result of wrong type; property missing type coercion in a custom resolver.

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/7d7b91d4acd7e0ba. Report an issue: GitHub.

Appendix: source

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

            channelModel.setOutboundEventChannelAdapter(new KafkaOperationsOutboundEventChannelAdapter(
                            kafkaOperations, partitionProvider, resolvedTopic, messageKeyProvider));
        }
    }

    protected Integer resolveExpressionAsInteger(String value, String attribute) {
        return resolveExpressionAsInteger(value, attribute, null);
    }

    protected Integer resolveExpressionAsInteger(String value, String attribute, Integer defaultValue) {
        Object resolved = resolveExpression(value);
        Integer result = defaultValue;
        if (resolved instanceof String) {
            result = Integer.parseInt((String) resolved);
        } 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 + "]");
        }

View on GitHub (pinned to d6d39ce1c6)