flowable/flowable-engine · error · FlowableIllegalArgumentException

Can only use a collection of String elements for referencing

Error message

Can only use a collection of String elements for referencing channel model key

What it means

SendEventTaskActivityBehavior.getChannelModels throws FlowableIllegalArgumentException when the resolved channel key expression yields a collection containing non-String elements. Channel keys must be Strings (optionally comma-separated lists), and any other element type makes channel resolution ambiguous.

Source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/SendEventTaskActivityBehavior.java:194

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

        Map<String, List<ExtensionElement>> extensionElements = execution.getCurrentFlowElement().getExtensionElements();
        if (extensionElements != null) {
            List<ExtensionElement> channelKeyElements = extensionElements.get("channelKey");
            if (channelKeyElements != null && !channelKeyElements.isEmpty()) {
                String channelKey = channelKeyElements.get(0).getElementText();
                if (StringUtils.isNotEmpty(channelKey)) {
                    ExpressionManager expressionManager = CommandContextUtil.getProcessEngineConfiguration(commandContext).getExpressionManager();
                    Expression expression = expressionManager.createExpression(channelKey);
                    Object resolvedChannelKey = expression.getValue(execution);
                    if (resolvedChannelKey instanceof Collection) {
                        for (Object next : (Collection) resolvedChannelKey) {
                            if (next instanceof String) {
                                String[] keys = ((String) next).split(",");
                                channelKeys.addAll(Arrays.asList(keys));

                            } else {
                                throw new FlowableIllegalArgumentException("Can only use a collection of String elements for referencing channel model key");

                            }
                        }

                    } else if (resolvedChannelKey instanceof String) {
                        String[] keys = ((String) resolvedChannelKey).split(",");
                        channelKeys.addAll(Arrays.asList(keys));

                    }
                }
            }
        }

        if (channelKeys.isEmpty()) {
            if (!sendOnSystemChannel) {
                // If the event is going to be send on the system channel then it is allowed to not define any other channels
                throw new FlowableException("No channel keys configured for " + execution);
            } else {

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Ensure the collection variable contains only String elements before the send event task executes
  2. Convert the collection (e.g. map each element to String) in a preceding service task or delegate
  3. If keys come from a bean expression, fix the bean to return List<String>
  4. Split numeric ids into their String keys when building the variable

Example fix

// before
List<Long> channelIds = repository.findIds();
execution.setVariable("channels", channelIds);
// after
List<String> channelKeys = repository.findIds().stream().map(String::valueOf).collect(Collectors.toList());
execution.setVariable("channels", channelKeys);
Defensive patterns

Strategy: type-guard

Validate before calling

// Validate channel variable before the send event task runs
Object channels = execution.getVariable("channels");
boolean valid = channels instanceof Collection
    && ((Collection<?>) channels).stream().allMatch(String.class::isInstance);

Type guard

public static boolean isStringCollection(Object o) {
    return o instanceof Collection && ((Collection<?>) o).stream().allMatch(String.class::isInstance);
}

Prevention

When it happens

Trigger: A send event task's channelKey expression resolves to a Collection whose elements are not Strings — e.g. a list of Integers, domain objects, or maps returned from a variable or bean expression.

Common situations: Passing a List<Long> of channel ids instead of String keys; a delegate/bean that builds the collection with the wrong element type; a variable set from JSON data where numbers were not converted to Strings.

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