flowable/flowable-engine · error · FlowableException

The kafka partition value was not found for the channel…

Error message

The kafka partition value was not found for the channel model with key <channelModel.getKey()>. One of eventField, delegateExpression should be set.

What it means

Thrown when the processor cannot build a KafkaPartitionProvider for an outbound channel: none of the supported sources for partition values (eventField, fixedValue via TopicPartition offsets, or delegateExpression) is configured on the channel model. The library requires at least one way to determine the Kafka target partition.

Solutions

  1. Set an eventField on the partition element naming the event field that carries the partition.
  2. Or set a delegateExpression resolving to a KafkaPartitionProvider.
  3. Or configure explicit partitions (TopicPartition offsets) so a RoundRobinKafkaPartitionProvider is created.
  4. Validate the channel model JSON before deployment (test deploy in a CI pipeline).

Example fix

// before
"partition": {}
// after
"partition": { "eventField": "partitionField" }
Defensive patterns

Strategy: validation

Validate before calling

boolean partitionsConfigured = partitionDef != null &&
    (partitionDef.eventField != null || partitionDef.delegateExpression != null || partitionDef.partitions != null);

Try / catch

try {
    deployChannel(channelModel);
} catch (FlowableException e) {
    if (e.getMessage() != null && e.getMessage().contains("partition value was not found")) {
        log.error("Channel {} missing partition config", channelModel.getKey(), e);
    } else { throw e; }
}

Prevention

When it happens

Trigger: Deploying/registering a Kafka outbound channel model whose partition definition has no eventField and no delegateExpression (and no TopicPartition offsets configured).

Common situations: Incomplete channel model JSON/YAML where the partition element was omitted or left empty; copying an inbound channel template to outbound use.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/51da87a6f7fb9beb. Report an issue: GitHub.

Appendix: source

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

        KafkaOutboundChannelModel.KafkaPartition partition = channelModel.getPartition();
        if (partition == null) {
            return null;
        }

        if (StringUtils.hasText(partition.getEventField())) {
            return new EventPayloadKafkaPartitionProvider(partition.getEventField());
        } else if (StringUtils.hasText(partition.getDelegateExpression())) {
            return resolveExpression(partition.getDelegateExpression(), KafkaPartitionProvider.class);
        } else if (StringUtils.hasText(partition.getRoundRobin())) {
            List<TopicPartitionOffset> tpo = new ArrayList<>();
            resolvePartitionAsInteger(channelModel.getTopic(), resolveExpression(partition.getRoundRobin()), tpo);
            List<Integer> partitions = new ArrayList<>(tpo.size());
            for (TopicPartitionOffset offset : tpo) {
                partitions.add(offset.getPartition());
            }
            return new RoundRobinKafkaPartitionProvider(partitions);
        } else {
            throw new FlowableException(
                    "The kafka partition value was not found for the channel model with key " + channelModel.getKey()
                            + ". One of eventField, delegateExpression should be set.");
        }
    }

    protected KafkaMessageKeyProvider<?> resolveKafkaMessageKeyProvider(KafkaOutboundChannelModel channelModel) {
        KafkaOutboundChannelModel.RecordKey recordKey = channelModel.getRecordKey();
        if (recordKey == null) {
            return null;
        }
        if (StringUtils.hasText(recordKey.getEventField())) {
            return new EventPayloadKafkaMessageKeyProvider(recordKey.getEventField());
        } else if (StringUtils.hasText(recordKey.getDelegateExpression())) {
            return resolveExpression(recordKey.getDelegateExpression(), KafkaMessageKeyProvider.class);
        } else if (recordKey.getFixedValue() != null) {
            String fixedValue = org.apache.commons.lang3.StringUtils.defaultIfBlank(recordKey.getFixedValue(), null);
            return ignore -> fixedValue;
        } else {

View on GitHub (pinned to d6d39ce1c6)