flowable/flowable-engine · error · IllegalArgumentException

partition in TopicPartition for topic

Error message

partition in TopicPartition for topic '<topic>' can't resolve '<resolvedValue>' as an Integer or String

What it means

Thrown by resolvePartitionAsInteger when a resolved partition value from the channel model is neither an Integer nor a String (nor an Iterable of such). The library only knows how to parse partitions given as integers or numeric strings, so any other resolved type is rejected with this IllegalArgumentException at channel definition processing time.

Solutions

  1. Ensure the partition attribute resolves to an Integer or a numeric String (e.g. "0-5,10" ranges are handled elsewhere; single values must be Integer or String).
  2. If using a delegateExpression, make the KafkaPartitionProvider return Integer partitions (convert Long to Integer).
  3. Check the event payload field referenced by eventField holds a number or numeric string, not an object.
  4. Wrap the value: return String.valueOf(rawValue) or Integer.valueOf(rawValue.toString()) in your provider.

Example fix

// before
public KafkaPartitionProvider provide() { return ignore -> 3L; } // Long
// after
public KafkaPartitionProvider provide() { return ignore -> 3; } // Integer
Defensive patterns

Strategy: validation

Validate before calling

Object v = resolvePartitionValue();
if (!(v instanceof Integer) && !(v instanceof String)) {
    throw new IllegalArgumentException("partition value must be Integer or String, got: " + v.getClass());
}

Type guard

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

Try / catch

try {
    channelRuntimeBuilder.build(channelModel);
} catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().contains("can't resolve")) {
        log.error("Bad partition value in channel model", e);
    } else { throw e; }
}

Prevention

When it happens

Trigger: A TopicPartition 'partition' attribute resolves (via eventField, fixedValue or delegateExpression) to a non-Integer, non-String object such as a Long, a Map, or a POJO that is not Iterable of Integer/String.

Common situations: A delegateExpression returning Long partition numbers, a fixedValue written as a JSON object instead of a number/string, or an event field carrying a non-numeric value.

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

Appendix: source

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

                    .collect(Collectors.toList());
            result.addAll(collected);
        }
        else if (resolvedValue instanceof Integer[]) {
            for (Integer partition : (Integer[]) resolvedValue) {
                result.add(new TopicPartitionOffset(topic, partition));
            }
        }
        else if (resolvedValue instanceof Integer) {
            result.add(new TopicPartitionOffset(topic, (Integer) resolvedValue));
        }
        else if (resolvedValue instanceof Iterable) {
            //noinspection unchecked
            for (Object object : (Iterable<Object>) resolvedValue) {
                resolvePartitionAsInteger(topic, object, result);
            }
        }
        else {
            throw new IllegalArgumentException(
                    "partition in TopicPartition for topic '" + topic + "' can't resolve '" + resolvedValue + "' as an Integer or String");
        }
    }

    /**
     * Parse a list of partitions into a {@link List}. Example: "0-5,10-15".
     * This parsing is the same as it is done in the Spring {@code KafkaListenerAnnotationBeanPostProcessor}.
     *
     * @param partsString the comma-delimited list of partitions/ranges.
     * @return the stream of partition numbers, sorted and de-duplicated.
     */
    protected Stream<Integer> parsePartitions(String partsString) {
        // This is the same as it is done in the Spring KafkaListenerAnnotationBeanPostProcessor#parsePartitions
        String[] partsStrings = partsString.split(",");
        if (partsStrings.length == 1 && !partsStrings[0].contains("-")) {
            return Stream.of(Integer.parseInt(partsStrings[0].trim()));
        }
        List<Integer> parts = new ArrayList<>();

View on GitHub (pinned to d6d39ce1c6)