flowable/flowable-engine · error · FlowableException

There are event definitions with key = ' ' and version = '…

Error message

There are ${results.size()} event definitions with key = '${channelDefinitionKey}' and version = '${eventVersion}'.

What it means

Thrown by MybatisChannelDefinitionDataManager.findChannelDefinitionByKeyAndVersion when the query selectChannelDefinitionsByKeyAndVersion returns more than one row for a (key, version) pair. Since key+version should uniquely identify a channel definition, duplicates mean the data is inconsistent. Note the message misleadingly says 'event definitions' even for channels.

Solutions

  1. Find and remove the duplicate rows: SELECT * FROM FLW_EV_CHANNEL_DEFINITION WHERE KEY_ = ? AND VERSION_ > 1 order by ID_ and delete the extras.
  2. Serialize deployments of the same key (e.g. distributed lock) so two nodes cannot insert the same version concurrently.
  3. Add a unique DB constraint on (KEY_, VERSION_) (and TENANT_ID_ where applicable) to fail fast on duplicates.
  4. Reconcile duplicates by keeping the definition whose DEPLOYMENT_ID_ matches the surviving deployment.

Example fix

-- before (duplicates present)
SELECT * FROM FLW_EV_CHANNEL_DEFINITION WHERE KEY_='myChannel' AND VERSION_=1;
-- after: keep one row, delete others
DELETE FROM FLW_EV_CHANNEL_DEFINITION WHERE KEY_='myChannel' AND VERSION_=1 AND ID_ != '<kept-id>';
Defensive patterns

Strategy: validation

Validate before calling

long n = eventRepositoryService.createChannelDefinitionQuery()
    .channelKey(key).channelDefinitionVersion(version).count();
if (n > 1) throw new IllegalStateException("duplicate channel definitions for key " + key + " v" + version + ", clean DB before lookup");

Try / catch

try {
    ch = manager.findChannelDefinitionByKeyAndVersion(key, version);
} catch (FlowableException e) {
    ch = dedupeAndRetry(key, version); // remove duplicate rows, then retry
}

Prevention

When it happens

Trigger: More than one FLW_EV_CHANNEL_DEFINITION row shares the same KEY_ and VERSION_ — typically from concurrent deployments of the same channel model racing to insert the same version number.

Common situations: Multiple cluster nodes deploying the same channel resource simultaneously without unique constraints or synchronization; manual DB inserts; retry logic re-inserting after a partial commit.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable-event-registry/src/main/java/org/flowable/eventregistry/impl/persistence/entity/data/impl/MybatisChannelDefinitionDataManager.java:117

    public ChannelDefinitionEntity findChannelDefinitionByDeploymentAndKeyAndTenantId(String deploymentId, String channelDefinitionKey, String tenantId) {
        Map<String, Object> parameters = new HashMap<>();
        parameters.put("deploymentId", deploymentId);
        parameters.put("channelDefinitionKey", channelDefinitionKey);
        parameters.put("tenantId", tenantId);
        return (ChannelDefinitionEntity) getDbSqlSession().selectOne("selectChannelDefinitionByDeploymentAndKeyAndTenantId", parameters);
    }
    
    @Override
    @SuppressWarnings("unchecked")
    public ChannelDefinitionEntity findChannelDefinitionByKeyAndVersion(String channelDefinitionKey, Integer eventVersion) {
        Map<String, Object> params = new HashMap<>();
        params.put("channelDefinitionKey", channelDefinitionKey);
        params.put("eventVersion", eventVersion);
        List<ChannelDefinitionEntity> results = getDbSqlSession().selectList("selectChannelDefinitionsByKeyAndVersion", params);
        if (results.size() == 1) {
            return results.get(0);
        } else if (results.size() > 1) {
            throw new FlowableException("There are " + results.size() + " event definitions with key = '" + channelDefinitionKey + "' and version = '" + eventVersion + "'.");
        }
        return null;
    }

    @Override
    @SuppressWarnings("unchecked")
    public ChannelDefinitionEntity findChannelDefinitionByKeyAndVersionAndTenantId(String channelDefinitionKey, Integer eventVersion, String tenantId) {
        Map<String, Object> params = new HashMap<>();
        params.put("channelDefinitionKey", channelDefinitionKey);
        params.put("eventVersion", eventVersion);
        params.put("tenantId", tenantId);
        List<ChannelDefinitionEntity> results = getDbSqlSession().selectList("selectChannelDefinitionsByKeyAndVersionAndTenantId", params);
        if (results.size() == 1) {
            return results.get(0);
        } else if (results.size() > 1) {
            throw new FlowableException("There are " + results.size() + " event definitions with key = '" + channelDefinitionKey + "' and version = '" + eventVersion + "' in tenant = '" + tenantId + "'.");
        }
        return null;

View on GitHub (pinned to d6d39ce1c6)