apache/maven · error · IllegalArgumentException

Duplicate dependency: {}

Error message

Duplicate dependency: {}

What it means

During consumer POM construction, DependencyMerger calls merge() when the same dependency key (groupId:artifactId:type:classifier) appears in a context where duplicates must be reconciled — the default strategy is to treat duplicates as an error, so merge() unconditionally throws IllegalArgumentException naming the duplicated key.

Source

Thrown at impl/maven-core/src/main/java/org/apache/maven/internal/transformation/impl/DefaultConsumerPomBuilder.java:298

            model = model.withDependencies(directDependencies.isEmpty() ? null : directDependencies.values());
        }

        return model;
    }

    private static boolean hasDependencyScope(Dependency dependency) {
        String scopeId = dependency.getScope();
        DependencyScope scope;
        if (scopeId == null || scopeId.isEmpty()) {
            scope = DependencyScope.COMPILE;
        } else {
            scope = DependencyScope.forId(scopeId);
        }
        return scope == null || !scope.isTransitive();
    }

    private Dependency merge(Dependency dep1, Dependency dep2) {
        throw new IllegalArgumentException("Duplicate dependency: " + getDependencyKey(dep1));
    }

    private static String getDependencyKey(org.apache.maven.api.Dependency dependency) {
        return dependency.getGroupId() + ":" + dependency.getArtifactId() + ":"
                + dependency.getType().id() + ":" + dependency.getClassifier();
    }

    private static String getDependencyKey(Dependency dependency) {
        return dependency.getGroupId() + ":" + dependency.getArtifactId() + ":"
                + (dependency.getType() != null ? dependency.getType() : "jar") + ":"
                + (dependency.getClassifier() != null ? dependency.getClassifier() : "");
    }

    private ModelBuilderResult buildModel(RepositorySystemSession session, MavenProject project, ModelSource src)
            throws ModelBuilderException {
        InternalSession iSession = InternalSession.from(session);
        ModelBuilderRequest.ModelBuilderRequestBuilder request = ModelBuilderRequest.builder();
        request.requestType(ModelBuilderRequest.RequestType.BUILD_CONSUMER);

View on GitHub (pinned to e4093d4e12)

Solutions

  1. Search the POM (and active profiles/parents) for the groupId:artifactId:type:classifier printed in the message and delete one of the entries
  2. If you need one version everywhere, declare it once in <dependencyManagement> and reference it without the version
  3. Check active profiles ('mvn help:active-profiles') — a dependency enabled by two profiles at once is a common source
  4. Re-run 'mvn help:effective-pom' to confirm only one entry survives after the fix

Example fix

<!-- before -->
<dependency><groupId>org.acme</groupId><artifactId>lib</artifactId><version>1.0</version></dependency>
<dependency><groupId>org.acme</groupId><artifactId>lib</artifactId><version>2.0</version></dependency>

<!-- after -->
<dependency><groupId>org.acme</groupId><artifactId>lib</artifactId><version>2.0</version></dependency>
Defensive patterns

Strategy: validation

Validate before calling

// lint the POM before building: no two deps share groupId:artifactId:type:classifier
Set<String> keys = new HashSet<>();
for (Dependency d : model.getDependencies()) {
    if (!keys.add(d.getGroupId() + ":" + d.getArtifactId() + ":" + d.getType() + ":" + d.getClassifier())) {
        throw new IllegalArgumentException("Duplicate dependency: " + d);
    }
}

Try / catch

catch (IllegalArgumentException e) {
    if (e.getMessage().startsWith("Duplicate dependency:")) {
        // remove the duplicate entry printed in the message, re-run
    }
}

Prevention

When it happens

Trigger: A POM (or effective POM after parent merge) containing two <dependency> entries with the same groupId:artifactId:type:classifier — e.g. the same GAV declared with two different versions/scopes, or a dependency repeated once directly and once via a profile that is active, hitting the merge path in DefaultConsumerPomBuilder.

Common situations: Copy-pasting a dependency and editing only the version; declaring the same artifact in both compile and test scope instead of using <exclusions> or dependencyManagement; profile-activated duplicates (dev vs default profiles both on); parent and child both declaring the same dependency with different classifiers resolved to the same key.

Related errors


AI-assisted analysis of apache/maven@e4093d4e12 (2026-08-21). Data as JSON: /api/errors/6bef9dfd4de016ba. Report an issue: GitHub.