flowable/flowable-engine · error · IllegalStateException

The [<attribute>] must resolve to a String. Resolved to [<cl

Error message

The [<attribute>] must resolve to a String. Resolved to [<class>] for [<value>]

What it means

RabbitChannelDefinitionProcessor resolves expression/string properties of a Rabbit inbound channel definition into endpoint attributes. resolveExpressionAsStringOrInteger only accepts values that resolve to a String or Integer; anything else (e.g. Boolean, Map, bean) triggers this IllegalStateException naming the offending attribute.

Source

Thrown at modules/flowable-event-registry-spring/src/main/java/org/flowable/eventregistry/spring/rabbit/RabbitChannelDefinitionProcessor.java:167

        if (channelDefinition.getOutboundEventChannelAdapter() == null && StringUtils.hasText(routingKey)) {
            String resolvedRoutingKey = resolve(routingKey);
            String exchange = resolve(channelDefinition.getExchange());
            channelDefinition
                .setOutboundEventChannelAdapter(new RabbitOperationsOutboundEventChannelAdapter(rabbitOperations, exchange, resolvedRoutingKey));
        }
    }

    protected String resolveExpressionAsStringOrInteger(String value, String attribute) {
        if (!StringUtils.hasLength(value)) {
            return null;
        }
        Object resolved = resolveExpression(value);
        if (resolved instanceof String) {
            return (String) resolved;
        } else if (resolved instanceof Integer) {
            return resolved.toString();
        } else {
            throw new IllegalStateException("The [" + attribute + "] must resolve to a String. "
                + "Resolved to [" + resolved.getClass() + "] for [" + value + "]");
        }
    }

    protected String[] resolveQueues(RabbitInboundChannelModel channelDefinition) {
        Collection<String> queues = channelDefinition.getQueues();
        if (queues == null) {
            throw new IllegalArgumentException("Queues in " + channelDefinition + " must not be null");
        }

        List<String> resultQueues = new ArrayList<>();

        for (String queue : queues) {
            resolveQueues(resolveExpression(queue), resultQueues, channelDefinition);
        }

        return resultQueues.toArray(new String[0]);
    }

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Fix the expression so it resolves to a String (or Integer, which is converted automatically)
  2. Wrap the resolved value: use toString()-style coercion or String.valueOf in the expression
  3. Inspect the resolved class name printed in the message to identify the wrong type
  4. Correct the channel definition XML/JSON so the field is a string literal or resolves to one

Example fix

// before (channel definition)
"concurrency": "${kafka.listener.concurrency}"  // resolves to Integer object bean
// after
"concurrency": "${kafka.listener.concurrencyString}"
Defensive patterns

Strategy: validation

Validate before calling

Object resolved = resolveExpression(value);
if (!(resolved instanceof String) && !(resolved instanceof Integer)) {
    throw new IllegalArgumentException("Attribute " + attribute + " must resolve to String/Integer, got " + resolved.getClass());
}

Type guard

boolean isStringResolvable(Object v) {
    return v instanceof String || v instanceof Integer;
}

Try / catch

try {
    String concurrency = processor.resolveExpressionAsStringOrInteger(raw, "concurrency");
} catch (IllegalStateException ex) {
    log.error("Channel attribute type wrong: {}", ex.getMessage());
}

Prevention

When it happens

Trigger: A channel definition attribute (e.g. 'concurrency', 'priority', or another string-typed property) is defined as an expression or property placeholder that resolves to a non-String/non-Integer object, such as a Boolean or a Collection bean.

Common situations: SpEL expression referencing the wrong bean or field type; YAML/JSON channel definition with a boolean or list where a string is expected; placeholder resolving to an unexpected type after refactoring.

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