{"record":{"id":"7b811eafb092f34c","repo":"apache/maven","slug":"unknown-lifecycle-phase-you-must-specify-a-v-7b811e","errorCode":null,"errorMessage":"Unknown lifecycle phase \"{}\". You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. Available lifecycle phases are: {}.","messagePattern":"Unknown lifecycle phase \"(.+?)\"\\. You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or <plugin-group-id>:<plugin-artifact-id>\\[:<plugin-version>\\]:<goal>\\. Available lifecycle phases are: (.+?)\\.","errorType":"exception","errorClass":"MavenException","httpStatus":null,"severity":"error","filePath":"impl/maven-core/src/main/java/org/apache/maven/lifecycle/internal/concurrent/BuildPlanExecutor.java","lineNumber":984,"sourceCode":"                Map<MavenProject, List<MavenProject>> projects, String lifecyclePhase) {\n\n            String resolvedPhase = getResolvedPhase(lifecyclePhase);\n            String mainPhase = resolvedPhase.startsWith(BEFORE)\n                    ? resolvedPhase.substring(BEFORE.length())\n                    : resolvedPhase.startsWith(AFTER)\n                            ? resolvedPhase.substring(AFTER.length())\n                            : resolvedPhase.startsWith(AT) ? resolvedPhase.substring(AT.length()) : resolvedPhase;\n\n            /*\n             * Determine the lifecycle that corresponds to the given phase.\n             */\n            Lifecycle lifecycle = lifecycles.stream()\n                    .filter(l -> l.allPhases().anyMatch(p -> mainPhase.equals(p.name())))\n                    .findFirst()\n                    .orElse(null);\n\n            if (lifecycle == null) {\n                throw new MavenException(new LifecyclePhaseNotFoundException(\n                        \"Unknown lifecycle phase \\\"\" + lifecyclePhase\n                                + \"\\\". You must specify a valid lifecycle phase\"\n                                + \" or a goal in the format <plugin-prefix>:<goal> or\"\n                                + \" <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. Available lifecycle phases are: \"\n                                + lifecycles.stream()\n                                        .flatMap(l -> l.allPhases().map(Lifecycle.Phase::name))\n                                        .collect(Collectors.joining(\", \"))\n                                + \".\",\n                        lifecyclePhase));\n            }\n\n            return calculateLifecycleMappings(projects, lifecycle, resolvedPhase);\n        }\n\n        public BuildPlan calculateLifecycleMappings(\n                Map<MavenProject, List<MavenProject>> projects, Lifecycle lifecycle, String lifecyclePhase) {\n            BuildPlan plan = new BuildPlan(projects);\n","sourceCodeStart":966,"sourceCodeEnd":1002,"githubUrl":"https://github.com/apache/maven/blob/e4093d4e120eac99d6bdce5ba67cace2f3085c97/impl/maven-core/src/main/java/org/apache/maven/lifecycle/internal/concurrent/BuildPlanExecutor.java#L966-L1002","documentation":"The concurrent BuildPlanExecutor resolves each task's phase (after stripping optional AFTER= and @ prefixes used for ordering/execution-id) against all registered lifecycles; when no lifecycle contains the phase name, it throws MavenException wrapping LifecyclePhaseNotFoundException, including the full list of valid phase names.","triggerScenarios":"Using the concurrent execution path with an invalid phase string — a typo like 'pakage', a phase only defined by an unloaded extension's custom lifecycle, or a malformed 'phase@execution-id' where mainPhase does not exist in any lifecycle.","commonSituations":"Typos in CLI goals or in <default-goal>; referencing custom lifecycle phases (e.g. from Tycho or document lifecycles) without the defining extension; scripts building 'phase@id' strings dynamically and emitting an empty/garbage phase.","solutions":["Match your phase against the 'Available lifecycle phases are:' list in the message and fix the typo","For plugin goals use <plugin-prefix>:<goal> or <groupId>:<artifactId>[:<version>]:<goal> syntax","Ensure the extension that contributes your custom lifecycle is loaded before the build plan is computed","Validate generated phase strings in scripts before passing them to Maven"],"exampleFix":"# before\nmvn pakage@fast   # 'pakage' is not a phase\n\n# after\nmvn package@fast","handlingStrategy":"validation","validationCode":"// validate task strings against registered lifecycles before planning\nSet<String> phases = lifecycles.stream().flatMap(l -> l.allPhases().map(Lifecycle.Phase::name)).collect(Collectors.toSet());\nString main = resolvedPhase.startsWith(\"+/\") ? resolvedPhase.substring(2) : resolvedPhase;\nif (!phases.contains(main)) throw new IllegalArgumentException(\"Unknown phase: \" + lifecyclePhase);","typeGuard":"boolean isKnownPhase(String task, Set<String> phases) {\n    String main = task.startsWith(\"+\") ? task.substring(1) : task;\n    int at = main.indexOf('@');\n    if (at >= 0) main = main.substring(0, at);\n    return phases.contains(main) || main.contains(\":\"); // plugin:goal form\n}","tryCatchPattern":"catch (MavenException e) {\n    if (e.getCause() instanceof LifecyclePhaseNotFoundException nfe) {\n        // nfe.getLifecyclePhase() names the bad phase; fix typo or load the custom lifecycle extension\n    }\n}","preventionTips":["Sanity-check generated 'phase@execution-id' strings before passing them to Maven","Load lifecycle-defining extensions in projects that use their phases","Reuse phase constants instead of string literals in build scripts"],"tags":["maven","lifecycle","phase","concurrent-build","cli"],"backgroundTag":"unknown-lifecycle-phase","analyzedSha":"e4093d4e120eac99d6bdce5ba67cace2f3085c97","analyzedAt":"2026-08-21T22:58:24.034Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}