flowable/flowable-engine · error · FlowableException

From activity '" + Arrays.toString(duplicates.toArray()) +…

Error message

From activity '" + Arrays.toString(duplicates.toArray()) + "' is mapped more than once

What it means

A migration document maps source activities to target activities; each source ('from') activity id may appear at most once. setActivityMigrationMappings detects duplicates across the supplied mappings and throws FlowableException listing the duplicated ids, preventing ambiguous migration instructions.

Solutions

  1. Deduplicate mappings by fromActivityId before setting them.
  2. Merge multiple targets of the same source activity into a single mapping with multiple target activity ids where supported.
  3. Review the duplicated ids in the message and remove the redundant mapping.

Example fix

// before
mappings.add(fromActivity("userTask1").toActivity("userTaskA"));
mappings.add(fromActivity("userTask1").toActivity("userTaskB"));

// after
mappings.add(fromActivity("userTask1").toActivity("userTaskA")); // keep only one mapping per from-activity
Defensive patterns

Strategy: validation

Validate before calling

Set<String> seen = new HashSet<>();
for (ActivityMigrationMapping m : mappings) {
    if (!seen.add(m.getFromActivityId())) throw new IllegalStateException("duplicate from-activity: " + m.getFromActivityId());
}

Try / catch

try {
    document.setActivityMigrationMappings(mappings);
} catch (FlowableException e) {
    logger.error("Duplicate activity mappings: " + e.getMessage());
}

Prevention

When it happens

Trigger: Calling setActivityMigrationMappings (typically via the builder's withActivityMappings during build) where two or more ActivityMigrationMapping entries have the same fromActivityId.

Common situations: Programmatically generating mappings in a loop that adds the same source activity twice; merging mapping lists from different sources; copy-paste editing migration mapping definitions.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/migration/ProcessInstanceMigrationDocumentImpl.java:213

    }

    @Override
    public String getPostUpgradeJavaDelegate() {
        return postUpgradeJavaDelegate;
    }

    @Override
    public String getPostUpgradeJavaDelegateExpression() {
        return postUpgradeJavaDelegateExpression;
    }

    public void setActivityMigrationMappings(List<ActivityMigrationMapping> activityMigrationMappings) {
        List<String> duplicates = findDuplicatedFromActivityIds(activityMigrationMappings);
        if (duplicates.isEmpty()) {
            this.activityMigrationMappings = activityMigrationMappings;
            this.activitiesLocalVariables = buildActivitiesLocalVariablesMap(activityMigrationMappings);
        } else {
            throw new FlowableException("From activity '" + Arrays.toString(duplicates.toArray()) + "' is mapped more than once");
        }
    }
    
    public void setEnableActivityMappings(List<EnableActivityMapping> enableActivityMappings) {
        this.enableActivityMappings = enableActivityMappings;
    }

    protected static List<String> findDuplicatedFromActivityIds(List<ActivityMigrationMapping> activityMigrationMappings) {
        //Frequency Map
        Map<String, Long> frequencyMap = activityMigrationMappings.stream()
            .filter(mapping -> !mapping.isToParentProcess())
            .flatMap(mapping -> mapping.getFromActivityIds().stream())
            .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

        //Duplicates
        List<String> duplicatedActivityIds = frequencyMap.entrySet()
            .stream()
            .filter(entry -> entry.getValue() > 1)

View on GitHub (pinned to d6d39ce1c6)