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
- Rename the custom lifecycle's phases to a unique, namespaced id (e.g. acme-compile instead of compile)
- Remove the custom phase that duplicates the standard one and bind goals to the standard phase instead
- 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
- Namespace custom phase ids (acme-compile, not compile)
- Test custom lifecycles against the full default lifecycle set in the plugin's IT suite
- Review loaded lifecycles with mvn -X whenever you add a lifecycle extension
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
- Ignored invalid goal specification '{}' from lifecycle mappi
- Found duplicated phase '{}' in '{}' lifecycle
- Unable to load plugin lifecycles
- Unknown lifecycle phase "{}". You must specify a valid lifec
- Unknown lifecycle phase "{}". You must specify a valid lifec
AI-assisted analysis of apache/maven@e4093d4e12 (2026-08-21).
Data as JSON: /api/errors/613704c05ca7a834.
Report an issue: GitHub.