apache/maven · warning

Duplicated lifecycle phase {}. Defined in {} but also in {}

Error message

Duplicated lifecycle phase {}. Defined in {} but also in {}

What it means

DefaultLifecycles builds a phase-to-lifecycle map across all installed lifecycles (default, clean, site, plus any contributed by packaging/extension plugins). When two lifecycles define the same phase, the first registration wins and this warning names both lifecycle ids; later lookups for that phase resolve to the first lifecycle only. The check also covers the v3 aliases of each lifecycle.

Source

Thrown at impl/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycles.java:116

    public Map<String, Lifecycle> getPhaseToLifecycleMap() {
        if (logger.isDebugEnabled() && !lifecyclesPrinted) {
            for (Lifecycle lifecycle : getLifeCycles()) {
                logger.debug("Lifecycle {}", lifecycle);
            }
            lifecyclesPrinted = true;
        }

        // If people are going to make their own lifecycles then we need to tell people how to namespace them correctly
        // so that they don't interfere with internally defined lifecycles.

        Map<String, Lifecycle> phaseToLifecycleMap = new HashMap<>();

        for (Lifecycle lifecycle : getLifeCycles()) {
            for (String phase : lifecycle.getPhases()) {
                // The first definition wins.
                Lifecycle original = phaseToLifecycleMap.put(phase, lifecycle);
                if (original != null && logger.isWarnEnabled()) {
                    logger.warn(
                            "Duplicated lifecycle phase {}. Defined in {} but also in {}",
                            phase,
                            original.getId(),
                            lifecycle.getId());
                }
            }
            if (lifecycle.getDelegate() != null) {
                for (org.apache.maven.api.Lifecycle.Alias alias :
                        lifecycle.getDelegate().aliases()) {
                    Lifecycle original = phaseToLifecycleMap.put(alias.v3Phase(), lifecycle);
                    if (original != null && logger.isWarnEnabled()) {
                        logger.warn(
                                "Duplicated lifecycle phase {}. Defined in {} but also in {}",
                                alias.v3Phase(),
                                original.getId(),
                                lifecycle.getId());
                    }
                }

View on GitHub (pinned to e4093d4e12)

Solutions

  1. Rename the custom lifecycle's phases to a unique, namespaced id (e.g. acme-compile instead of compile)
  2. Remove the custom phase that duplicates the standard one and bind goals to the standard phase instead
  3. List loaded lifecycles (mvn -X) to find which two lifecycle ids collide, then fix the one you control

Example fix

<!-- before (custom lifecycle hijacks a standard phase) -->
<lifecycle>
  <id>acme</id>
  <phases>
    <phase>compile</phase>
  </phases>
</lifecycle>
<!-- after (namespaced phase id) -->
<lifecycle>
  <id>acme</id>
  <phases>
    <phase>acme-compile</phase>
  </phases>
</lifecycle>
Defensive patterns

Strategy: validation

Validate before calling

// in the lifecycle extension's tests: assert no phase collides with standard lifecycles
Set<String> standard = Set.of(/* default+clean+site phases */ "compile", "test", "package", "verify", "install", "deploy", "clean", "site");
for (String phase : myLifecycle.getPhases()) {
    if (standard.contains(phase)) {
        throw new IllegalStateException("Custom lifecycle redefines standard phase: " + phase);
    }
}

Prevention

When it happens

Trigger: A custom lifecycle contributed by a core extension or packaging plugin declares a phase id that the default lifecycle (or an earlier-loaded custom lifecycle) already owns - e.g. redefining 'compile' or 'package'.

Common situations: In-house packaging plugins reusing standard phase names to 'override' them; multiple custom lifecycle extensions loaded together; upgrading a lifecycle extension that grew new phases that clash.

Related errors


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