flowable/flowable-engine · error · IllegalArgumentException

Channel definition cannot resolve as a String[] or a String

Error message

Channel definition <channelDefinition> cannot resolve <resolvedValue> as a String[] or a String

What it means

resolveTopics resolves the topics attribute of a Kafka inbound channel; the resolved value must be a String, a String[]/array of Strings, or an Iterable containing Strings. Any other resolved type triggers IllegalArgumentException naming the channel definition and the offending value. This validates the multi-topic configuration at endpoint creation time.

Solutions

  1. Ensure every topic entry is a String, e.g. topics: ["orders", "payments"].
  2. Fix the placeholder/expression so it resolves to String[] or List<String>.
  3. If using a Map, flatten to a list of keys (e.g. ${...keys} style) before assigning.
  4. Quote numeric topic names so they stay Strings.

Example fix

// before
topics: [101, 102]

// after
topics: ["101", "102"]
Defensive patterns

Strategy: validation

Validate before calling

Object resolved = resolveExpression(topicsValue);
boolean ok = resolved instanceof String
    || resolved instanceof String[]
    || (resolved instanceof Iterable<?> it && StreamSupport.stream(it.spliterator(), false).allMatch(o -> o instanceof String));
if (!ok) throw new IllegalArgumentException("topics must resolve to String or String[]/Iterable<String>");

Try / catch

try { ... } catch (IllegalArgumentException e) { if (e.getMessage().contains("as a String[] or a String")) { log.error("Bad topics config: {}", e.getMessage()); } else throw e; }

Prevention

When it happens

Trigger: The channel's topics attribute expression resolves to e.g. a List of Integers, a Map, or a single non-String object; resolveTopics recursion hits an element that is neither String, String[], nor Iterable.

Common situations: topics: [1,2,3] numeric list in model; placeholder points to a Map of topic->options; mixed-type array from environment variables.

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

Appendix: source

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

        }

        return resultTopics;
    }

    protected void resolveTopics(Object resolvedValue, List<String> result, KafkaInboundChannelModel channelDefinition) {
        if (resolvedValue instanceof String[]) {
            for (String object : (String[]) resolvedValue) {
                resolveTopics(object, result, channelDefinition);
            }

        } else if (resolvedValue instanceof String) {
            result.add((String) resolvedValue);
        } else if (resolvedValue instanceof Iterable) {
            for (Object object : (Iterable<?>) resolvedValue) {
                resolveTopics(object, result, channelDefinition);
            }
        } else {
            throw new IllegalArgumentException(
                "Channel definition " + channelDefinition + " cannot resolve " + resolvedValue + " as a String[] or a String");
        }
    }

    protected Pattern resolvePattern(KafkaInboundChannelModel channelModel) {
        Pattern pattern = null;
        String topicPattern = channelModel.getTopicPattern();
        if (StringUtils.hasText(topicPattern)) {
            Object resolved = resolveExpression(topicPattern);
            if (resolved instanceof String) {
                pattern = Pattern.compile((String) resolved);
            } else if (resolved instanceof Pattern) {
                pattern = (Pattern) resolved;
            } else if (resolved != null) {
                throw new IllegalStateException(
                    "topicPattern in channel model [ " + channelModel + " ] must resolve to a Pattern or String, not " + resolved.getClass());
            }
        }

View on GitHub (pinned to d6d39ce1c6)