flowable/flowable-engine · error · FlowableException

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

Error message

There are ${results.size()} event definitions with key = '${eventDefinitionKey}' and version = '${eventVersion}' in tenant = '${tenantId}'.

What it means

Thrown by MybatisEventDefinitionDataManager.findEventDefinitionByKeyAndVersionAndTenantId when the tenant-scoped key+version query returns more than one row. In a multi-tenant setup, (TENANT_ID_, KEY_, VERSION_) must be unique; duplicates mean the same event definition version was persisted twice for that tenant.

Solutions

  1. Remove duplicate FLW_EV_DATABASE_DEFINITION rows matching the same TENANT_ID_, KEY_, VERSION_, keeping one.
  2. Make tenant bootstrap deployments idempotent: check EventDefinitionQuery for the tenant before deploying.
  3. Add a unique constraint on (TENANT_ID_, KEY_, VERSION_).
  4. Use a distributed lock or single deployer node for event registry deployments.

Example fix

// before
eventRepositoryService.createDeployment().addClasspathResource(res).tenantId(tenantId).deploy(); // all nodes
// after
if (eventRepositoryService.createEventDefinitionQuery().eventDefinitionKey(key)
        .eventDefinitionVersion(version).tenantId(tenantId).count() == 0) {
    eventRepositoryService.createDeployment().addClasspathResource(res).tenantId(tenantId).deploy();
}
Defensive patterns

Strategy: validation

Validate before calling

long n = eventRepositoryService.createEventDefinitionQuery()
    .eventDefinitionKey(key).eventDefinitionVersion(version).tenantId(tenantId).count();
if (n > 1) throw new IllegalStateException("duplicate tenant event definitions for " + key + " v" + version + " tenant " + tenantId);

Try / catch

try {
    def = manager.findEventDefinitionByKeyAndVersionAndTenantId(key, version, tenantId);
} catch (FlowableException e) {
    def = dedupeTenantRowsAndRetry(key, version, tenantId);
}

Prevention

When it happens

Trigger: Concurrent per-tenant deployment of the same event model key/version on multiple nodes; both inserts commit and the next lookup throws FlowableException.

Common situations: Every application instance running tenant bootstrap deployment code at startup; duplicated migration scripts; manual copies of definition rows across tenants done incorrectly (same tenant twice).

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/498833081aeba8c4. Report an issue: GitHub.

Appendix: source

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

            return results.get(0);
        } else if (results.size() > 1) {
            throw new FlowableException("There are " + results.size() + " event definitions with key = '" + eventDefinitionKey + "' and version = '" + eventVersion + "'.");
        }
        return null;
    }

    @Override
    @SuppressWarnings("unchecked")
    public EventDefinitionEntity findEventDefinitionByKeyAndVersionAndTenantId(String eventDefinitionKey, Integer eventVersion, String tenantId) {
        Map<String, Object> params = new HashMap<>();
        params.put("eventDefinitionKey", eventDefinitionKey);
        params.put("eventVersion", eventVersion);
        params.put("tenantId", tenantId);
        List<EventDefinitionEntity> results = getDbSqlSession().selectList("selectEventDefinitionsByKeyAndVersionAndTenantId", 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 = '" + eventDefinitionKey + "' and version = '" + eventVersion + "' in tenant = '" + tenantId + "'.");
        }
        return null;
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<EventDefinition> findEventDefinitionsByNativeQuery(Map<String, Object> parameterMap) {
        return getDbSqlSession().selectListWithRawParameter("selectEventDefinitionByNativeQuery", parameterMap);
    }

    @Override
    public long findEventDefinitionCountByNativeQuery(Map<String, Object> parameterMap) {
        return (Long) getDbSqlSession().selectOne("selectEventDefinitionCountByNativeQuery", parameterMap);
    }

    @Override
    public void updateEventDefinitionTenantIdForDeployment(String deploymentId, String newTenantId) {
        HashMap<String, Object> params = new HashMap<>();

View on GitHub (pinned to d6d39ce1c6)