flowable/flowable-engine · error · PvmException

duplicate activity id

Error message

duplicate activity id '${activityId}'

What it means

PvmException thrown by ScopeImpl.createActivity when an activity id is provided that already exists in the process definition. Activity ids must be unique within the whole definition, since findActivity and namedActivities rely on global uniqueness. Null ids are allowed (anonymous activities) and are not checked.

Solutions

  1. Use unique activity ids across the entire process definition.
  2. Fix duplicate ids in the BPMN source before deployment.
  3. Generate unique ids programmatically (e.g. prefix per sub-scope or use a counter/UUID) when building dynamically.

Example fix

// before
scope.createActivity("taskA");
scope.createActivity("taskA"); // duplicate
// after
scope.createActivity("taskA");
scope.createActivity("taskB"); // unique id
Defensive patterns

Strategy: validation

Validate before calling

if (definition.findActivity(activityId) != null) {
  throw new IllegalArgumentException("activity id '" + activityId + "' already exists in this process definition");
}
scope.createActivity(activityId);

Try / catch

try {
  scope.createActivity(activityId);
} catch (PvmException e) {
  if (e.getMessage() != null && e.getMessage().contains("duplicate activity id")) {
    // rekey or skip the activity
    scope.createActivity(activityId + "_2");
  }
}

Prevention

When it happens

Trigger: Creating two activities with the same id on the same (or nested) scope, or the builder's activity(id) helper invoked twice with the same id before buildProcessDefinition.

Common situations: Duplicate element ids in BPMN XML, merging two models into one definition, or loops in a generator that reuse ids.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/pvm/process/ScopeImpl.java:66

        }
        for (ActivityImpl activity : activities) {
            ActivityImpl nestedActivity = activity.findActivity(activityId);
            if (nestedActivity != null) {
                return nestedActivity;
            }
        }
        return null;
    }

    public ActivityImpl createActivity() {
        return createActivity(null);
    }

    public ActivityImpl createActivity(String activityId) {
        ActivityImpl activity = new ActivityImpl(activityId, processDefinition);
        if (activityId != null) {
            if (processDefinition.findActivity(activityId) != null) {
                throw new PvmException("duplicate activity id '" + activityId + "'");
            }
            namedActivities.put(activityId, activity);
        }
        activity.setParent(this);
        activities.add(activity);
        return activity;
    }

    public boolean contains(ActivityImpl activity) {
        if (namedActivities.containsKey(activity.getId())) {
            return true;
        }
        for (ActivityImpl nestedActivity : activities) {
            if (nestedActivity.contains(activity)) {
                return true;
            }
        }
        return false;

View on GitHub (pinned to d6d39ce1c6)