flowable/flowable-engine · error · FlowableException

There are app definitions with key = '' and version = ''

Error message

There are  app definitions with key = '' and version = ''

What it means

FlowableException thrown by MybatisAppDefinitionDataManager.findAppDefinitionByKeyAndVersion when the query selectAppDefinitionsByKeyAndVersion returns more than one row. The data layer expects (key, version) to be unique; duplicates indicate corrupted data, so it refuses to pick one arbitrarily.

Source

Thrown at modules/flowable-app-engine/src/main/java/org/flowable/app/engine/impl/persistence/entity/data/impl/MybatisAppDefinitionDataManager.java:91

    @Override
    public AppDefinitionEntity findAppDefinitionByDeploymentAndKeyAndTenantId(String deploymentId, String appDefinitionKey, String tenantId) {
        Map<String, Object> parameters = new HashMap<>();
        parameters.put("deploymentId", deploymentId);
        parameters.put("appDefinitionKey", appDefinitionKey);
        parameters.put("tenantId", tenantId);
        return (AppDefinitionEntity) getDbSqlSession().selectOne("selectAppDefinitionByDeploymentAndKeyAndTenantId", parameters);
    }

    @Override
    public AppDefinitionEntity findAppDefinitionByKeyAndVersion(String appDefinitionKey, Integer appDefinitionVersion) {
        Map<String, Object> params = new HashMap<>();
        params.put("appDefinitionKey", appDefinitionKey);
        params.put("appDefinitionVersion", appDefinitionVersion);
        List<AppDefinitionEntity> results = getDbSqlSession().selectList("selectAppDefinitionsByKeyAndVersion", params);
        if (results.size() == 1) {
            return results.get(0);
        } else if (results.size() > 1) {
            throw new FlowableException("There are " + results.size() + " app definitions with key = '" + appDefinitionKey + "' and version = '" + appDefinitionVersion + "'.");
        }
        return null;
    }

    @Override
    @SuppressWarnings("unchecked")
    public AppDefinitionEntity findAppDefinitionByKeyAndVersionAndTenantId(String appDefinitionKey, Integer appDefinitionVersion, String tenantId) {
        Map<String, Object> params = new HashMap<>();
        params.put("appDefinitionKey", appDefinitionKey);
        params.put("appDefinitionVersion", appDefinitionVersion);
        params.put("tenantId", tenantId);
        List<AppDefinitionEntity> results = getDbSqlSession().selectList("selectAppDefinitionsByKeyAndVersionAndTenantId", params);
        if (results.size() == 1) {
            return results.get(0);
        } else if (results.size() > 1) {
            throw new FlowableException("There are " + results.size() + " app definitions with key = '" + appDefinitionKey + "' and version = '" + appDefinitionVersion + "'.");
        }
        return null;

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Query the DB: SELECT * FROM ACT_APP_APPDEF WHERE KEY_ = ? AND VERSION_ = ? and delete/merge duplicates keeping the correct row
  2. Add/restore the unique constraint on (KEY_, VERSION_) if your setup guarantees uniqueness
  3. If duplicates are legitimate tenant variants, use the *AndTenantId lookup instead
  4. Re-deploy the affected app after cleaning to ensure consistent state

Example fix

// before
-- find duplicates
SELECT KEY_, VERSION_, COUNT(*) FROM ACT_APP_APPDEF GROUP BY KEY_, VERSION_ HAVING COUNT(*) > 1;
// after
-- keep one row, remove the rest, then re-run the lookup
Defensive patterns

Strategy: try-catch

Validate before calling

// detect duplicates before lookup
// SELECT KEY_, VERSION_, COUNT(*) FROM ACT_APP_APPDEF GROUP BY KEY_, VERSION_ HAVING COUNT(*) > 1

Try / catch

try {
    AppDefinition def = ...findAppDefinitionByKeyAndVersion(key, version);
} catch (FlowableException e) {
    // clean duplicates in ACT_APP_APPDEF, then retry
}

Prevention

When it happens

Trigger: Calling an API that resolves an app definition by key+version when ACT_APP_APPDEF contains multiple rows with the same key and version — typically after manual inserts, failed migrations, or concurrent double-deployment bugs.

Common situations: Database manually edited or rows copied between environments; a broken import script inserted duplicates; historic Flowable bug or non-unique index in an old schema; tenant variants created where key+version uniqueness was assumed.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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