flowable/flowable-engine · error · FlowableException

The deployment contains channel definition with the same…

Error message

The deployment contains channel definition with the same key, this is not allowed

What it means

ChannelDefinitionDeploymentHelper.verifyChannelDefinitionsDoNotShareKeys throws FlowableException when a single deployment contains two or more channel definitions with the same key. Keys must be unique within a deployment because a key identifies the definition and its versioning.

Solutions

  1. Rename one of the duplicate channel keys in the event registry resource and redeploy.
  2. Split the definitions into separate deployments if they are intentionally distinct resources.
  3. Before deploying, collect channel keys from the model and assert uniqueness.

Example fix

// before (event registry json)
// <channel key="orders" ... /> ... <channel key="orders" ... />
// after
// <channel key="orders-inbound" ... /> <channel key="orders-outbound" ... />
Defensive patterns

Strategy: validation

Validate before calling

Set<String> keys = channelDefinitions.stream().map(ChannelDefinitionEntity::getKey).collect(Collectors.toSet());
if (keys.size() != channelDefinitions.size()) throw new IllegalStateException("Duplicate channel keys in deployment");

Try / catch

try { repositoryService.deploy(deployment); } catch (FlowableException e) { log.error("Deployment rejected: {}", e.getMessage()); }

Prevention

When it happens

Trigger: Deploying an event registry resource (or set of resources) that declares two channels with the same key, e.g. duplicated channel entries in one .eventreg model or two resources in one deployment defining the same channel key.

Common situations: Copy-pasting a channel block in the event registry JSON and forgetting to change the key, merging model files that both define the same channel, or programmatically adding the same channel definition twice to one deployment.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable-event-registry/src/main/java/org/flowable/eventregistry/impl/deployer/ChannelDefinitionDeploymentHelper.java:45

import org.flowable.eventregistry.impl.util.CommandContextUtil;

/**
 * Methods for working with deployments. Much of the actual work of {@link EventDefinitionDeployer} is done by orchestrating the different pieces of work this class does; by having them here, we allow
 * other deployers to make use of them.
 */
public class ChannelDefinitionDeploymentHelper {

    /**
     * Verifies that no two channel definitions share the same key, to prevent database unique index violation.
     * 
     * @throws FlowableException
     *             if any two channel definitions have the same key
     */
    public void verifyChannelDefinitionsDoNotShareKeys(Collection<ChannelDefinitionEntity> channelDefinitions) {
        Set<String> keySet = new LinkedHashSet<>();
        for (ChannelDefinitionEntity channelDefinition : channelDefinitions) {
            if (keySet.contains(channelDefinition.getKey())) {
                throw new FlowableException("The deployment contains channel definition with the same key, this is not allowed");
            }
            keySet.add(channelDefinition.getKey());
        }
    }

    /**
     * Updates all the channel definition entities to match the deployment's values for tenant, engine version, and deployment id.
     */
    public void copyDeploymentValuesToEventDefinitions(EventDeploymentEntity deployment, List<ChannelDefinitionEntity> channelDefinitions) {
        String tenantId = deployment.getTenantId();
        String deploymentId = deployment.getId();

        for (ChannelDefinitionEntity channelDefinition : channelDefinitions) {

            // event definition inherits the tenant id
            if (tenantId != null) {
                channelDefinition.setTenantId(tenantId);
            }

View on GitHub (pinned to d6d39ce1c6)