apache/maven · critical · IllegalArgumentException
Found duplicated phase '{}' in '{}' lifecycle
Error message
Found duplicated phase '{}' in '{}' lifecycle What it means
IllegalArgumentException thrown from DefaultLifecycleRegistry's constructor while validating every registered lifecycle: within a single lifecycle, a phase name may appear only once. Because this fires during Sisu component wiring at container startup, a duplicate poisons the whole container — Maven fails before any project builds.
Source
Thrown at impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLifecycleRegistry.java:118
public static final String SCOPE_TEST = DependencyScope.TEST.id();
private final List<LifecycleProvider> providers;
public DefaultLifecycleRegistry() {
this(Collections.emptyList());
}
@Inject
public DefaultLifecycleRegistry(List<LifecycleProvider> providers) {
List<LifecycleProvider> p = new ArrayList<>(providers);
p.add(() -> List.of(new CleanLifecycle(), new DefaultLifecycle(), new SiteLifecycle()));
this.providers = p;
// validate lifecycle
for (Lifecycle lifecycle : this) {
Set<String> set = new HashSet<>();
lifecycle.allPhases().forEach(phase -> {
if (!set.add(phase.name())) {
throw new IllegalArgumentException(
"Found duplicated phase '" + phase.name() + "' in '" + lifecycle.id() + "' lifecycle");
}
});
}
}
static String getImplementationVersion(Class<?> clazz) {
Package packageInfo = clazz.getPackage();
return packageInfo != null ? packageInfo.getImplementationVersion() : null;
}
@Override
public Iterator<Lifecycle> iterator() {
return stream().toList().iterator();
}
@Override
public Stream<Lifecycle> stream() {View on GitHub (pinned to e4093d4e12)
Solutions
- Open the failing lifecycle (its id is in the message); in the contributing plugin's lifecycle mapping, remove or rename the duplicated phase
- Reference built-in phases instead of re-declaring them in a custom lifecycle
- Pin or upgrade the plugin that contributes the custom lifecycle to a version built for the Maven version in use
Defensive patterns
Strategy: validation
Validate before calling
// Validate a custom lifecycle definition before contributing it
Set<String> seen = new HashSet<>();
for (Phase phase : customLifecycle.allPhases()) {
if (!seen.add(phase.name())) {
throw new IllegalArgumentException(
"duplicate phase '" + phase.name() + "' in lifecycle " + customLifecycle.id());
}
} Prevention
- Lint plugin lifecycle mappings for duplicate phase names in CI
- Do not copy built-in default/clean/site phases into custom packagings; reference them
- Test custom-packaging plugins against the exact Maven version on container startup before release
When it happens
Trigger: A LifecycleProvider (typically a plugin contributing custom packaging/lifecycles via its descriptor's lifecycle mappings) returns phases whose name() duplicates another phase in the same lifecycle id — e.g. a custom packaging re-declaring 'compile' or copying the default lifecycle's phases into its own list.
Common situations: Custom packaging plugins with hand-written lifecycle definitions; upgrading Maven major versions where provider APIs changed and previously-shadowed mappings now collide with built-in lifecycles (default, clean, site).
Related errors
- Cannot read metadata from '{}'
- Unable to lookup org.eclipse.aether.RepositorySystem
- Unable to load plugin lifecycles
- No binding to construct an instance for key {}. Existing bi
- Only String keys are supported for maps: {}
AI-assisted analysis of apache/maven@e4093d4e12 (2026-08-21).
Data as JSON: /api/errors/8fd3b5d3010e51df.
Report an issue: GitHub.