apache/maven · warning
Illegal call to phase '{}'. The main phase '{}' will be used
Error message
Illegal call to phase '{}'. The main phase '{}' will be used instead. What it means
ConcurrentLifecycleStarter.calculateTaskSegments() validates each requested task; isBeforeOrAfterPhase() checks task.startsWith(Lifecycle.BEFORE) or AFTER — the pre-/post- companion phases like pre-clean, post-clean, post-deploy that only exist as hooks inside a full lifecycle. Directly invoking one is illegal, so Maven maps it via PhaseId.of(task).phase() to the main phase and warns that the main phase will be executed instead.
Source
Thrown at impl/maven-core/src/main/java/org/apache/maven/lifecycle/internal/concurrent/ConcurrentLifecycleStarter.java:147
&& !rootProject.getDefaultGoal().isEmpty())) {
tasks = Stream.of(rootProject.getDefaultGoal().split("\\s+"))
.filter(g -> !g.isEmpty())
.collect(Collectors.toList());
}
return calculateTaskSegments(session, tasks);
}
public List<TaskSegment> calculateTaskSegments(MavenSession session, List<String> tasks) throws Exception {
List<TaskSegment> taskSegments = new ArrayList<>(tasks.size());
TaskSegment currentSegment = null;
for (String task : tasks) {
if (isBeforeOrAfterPhase(task)) {
String prevTask = task;
task = PhaseId.of(task).phase();
logger.warn("Illegal call to phase '{}'. The main phase '{}' will be used instead.", prevTask, task);
}
if (isGoalSpecification(task)) {
// "pluginPrefix[:version]:goal" or "groupId:artifactId[:version]:goal"
lifecyclePluginResolver.resolveMissingPluginVersions(session.getTopLevelProject(), session);
MojoDescriptor mojoDescriptor =
mojoDescriptorCreator.getMojoDescriptor(task, session, session.getTopLevelProject());
boolean aggregating = mojoDescriptor.isAggregator() || !mojoDescriptor.isProjectRequired();
if (currentSegment == null || currentSegment.isAggregating() != aggregating) {
currentSegment = new TaskSegment(aggregating);
taskSegments.add(currentSegment);
}
currentSegment.getTasks().add(new GoalTask(task));
} else {View on GitHub (pinned to e4093d4e12)
Solutions
- Invoke the main phase instead: 'mvn clean' instead of 'mvn post-clean', 'mvn deploy' instead of 'mvn post-deploy'.
- To run only a hook's bound plugin executions, invoke the plugin goals directly (e.g. 'mvn clean:clean') or bind them to a custom phase.
- Audit build scripts/CI yaml for task names starting with pre-/post- that are lifecycle phases.
Example fix
# before mvn post-clean # warns: Illegal call to phase 'post-clean'. 'clean' used # after mvn clean
Defensive patterns
Strategy: validation
Validate before calling
# guard: reject hook phases (pre-*/post-*) as tasks before invoking Maven
for task in "$@"; do
case "$task" in
pre-*|post-*) echo "illegal direct phase: $task (use the main lifecycle phase)"; exit 2;;
esac
done
mvn "$@" Prevention
- Treat pre-clean/post-clean/pre-site/post-site/post-deploy as hooks, never as standalone goals.
- To execute only hook-bound executions, invoke the specific plugin goals instead of the hook phase.
When it happens
Trigger: Passing a hook phase as a task on the command line or via goals: 'mvn post-clean', 'mvn pre-site', 'mvn post-deploy' — anything starting with 'pre-' or 'post-' that resolves to a lifecycle phase id.
Common situations: Scripts trying to run 'only the cleanup hook' or CI jobs copying phase names from docs; users assuming pre-*/post-* are independently runnable phases; migration from tools where such phases are first-class.
Related errors
- Unknown lifecycle phase "{}". You must specify a valid lifec
- Unknown lifecycle phase "{}". You must specify a valid lifec
- The goal you specified requires a project to execute but the
- No goals have been specified for this build. You must specif
- Unbounded range: {}
AI-assisted analysis of apache/maven@e4093d4e12 (2026-08-21).
Data as JSON: /api/errors/2f1d522683ffcdfe.
Report an issue: GitHub.