Conversation
When a user runs 'mvn' without any arguments and there is no pom.xml in the current directory, Maven currently fails with a confusing BUILD FAILURE / NoGoalSpecifiedException error. This is surprising and unhelpful: the user likely just typed 'mvn' by mistake or wants to explore what Maven can do. This commit improves the UX by detecting this specific situation early in MavenInvoker.postCommands() — after DI is fully set up but before the build is attempted — and printing the usage (same output as mvn -h) then exiting with code 0, instead of failing. The check is deliberately narrow: it only fires when BOTH conditions are true: 1. No goals or lifecycle phases were specified on the command line. 2. No POM file is present in the current directory (or via -f). If a POM is found, Maven proceeds as before: the default goal (if any) is executed, or the existing NoGoalSpecifiedException is reported. This preserves existing behavior for all normal project builds. Fixes: https://github.com/apache/maven/issues/XXXXX
When the -f/--file option points to a non-existent file, Maven previously printed redundant information: POM file X does not exist (bare, no prefix - source TBD) [ERROR] Error executing Maven. [ERROR] Error determining top directory [ERROR] Caused by: POM file X does not exist The 'Error determining top directory' wrapper and 'Caused by:' repetition added noise without helping the user understand what went wrong. Now, when getTopDirectory() throws an IllegalArgumentException (a user- facing error with a self-explanatory message), we log the message directly instead of wrapping it. The output is now: [ERROR] Error executing Maven. [ERROR] POM file X specified with the -f/--file command line argument does not exist The same pattern is applied to getRootDirectory() for consistency.
The shell script's find_file_argument_basedir() already validated the -f argument and printed an error, but the exit 1 was inside a subshell so it did not stop the main script from launching the JVM, which then printed the same error again through the Java logging infrastructure. Fix: propagate the subshell exit code through find_maven_basedir() and bail out before launching the JVM if the -f argument is invalid. Also add the [ERROR] prefix to the shell-side error messages to match Maven's standard logging format.
gnodet-bot
left a comment
There was a problem hiding this comment.
Solid approach — three cleanly separated concerns, each independently correct.
1. Print usage on mvn with no goals and no POM (MavenInvoker.postCommands): The guard goals().orElse(List.of()).isEmpty() && determinePom(...) == null is precise — exits 0 with help only when no POM is found, preserving default-goal behavior when a POM exists. Uses the exact same displayHelp + ExitException(0) pattern as helpOrVersionAndMayExit, and fires after lookup() so DI is ready for determinePom().
2. Clean -f error messages (BaseParser): Catching IllegalArgumentException before the generic catch (Exception) lets the already-descriptive message from getTopDirectory() ("POM file X ... does not exist") print directly instead of being wrapped in "Error determining top directory". Same pattern applied symmetrically to getRootDirectory.
3. Shell exit code propagation (mvn): Previously find_file_argument_basedir's exit 1 only left the subshell — now captured via rc=$?; [ $rc -ne 0 ] && exit $rc and re-checked after find_maven_basedir. The echo → printf '[ERROR] ...' switch adds consistency with Maven's Java-side error formatting and better POSIX portability.
No issues found.
This review was generated by an AI agent, Hermès on behalf of @gnodet.
|
I would like to suggest a better phrasing. Instead of Maybe this is sufficient: |
|
Looks good, and it lines up with the dev@ consensus on the "Print usage when no arguments are given" thread — POM present → the default goal (if any) still runs, otherwise print usage. Keying the Java check on POM presence rather than trying to detect a default goal also neatly side-steps the "detecting a default goal needs the built model, very early in startup" concern raised there. 👍 One cross-platform gap: the echo POM file "%FILE_ARG%" specified the -f/--file command-line argument does not exist >&2
echo Directory "%POM_DIR%" extracted from the -f/--file command-line argument "%FILE_ARG%" does not exist >&2So Windows users still get the un-prefixed form. Those should become: echo [ERROR] POM file "%FILE_ARG%" specified with the -f/--file command-line argument does not exist >&2
echo [ERROR] Directory "%POM_DIR%" extracted from the -f/--file command-line argument "%FILE_ARG%" does not exist >&2(also fixes a stray The harder half of your Unix change needs no Windows counterpart, though: the subshell-exit propagation (so a bad |
|
Heads-up: CI is red on this PR — All the path-conversion assertions pass ( output=`run_mvn_with_args CYGWIN_NT-10.0 "$stub_dir" -f /cygdrive/c/temp/pom.xml validate`Root cause: this PR makes a non-existent The behavior change is right; the test just needs to catch up — e.g. |
Problem
When a user types
mvnwithout any arguments and there is nopom.xmlin the current directory, Maven currently fails with:This is surprising and unhelpful — especially for new users. Tools like
javaandjavacprint usage in this situation.The discussion on the dev list ("Print usage when no arguments are given" Sep 2026) confirmed broad agreement that the current behavior should be improved, with the key constraint that default goals must still work.
Additionally, when the
-f/--fileoption points to a non-existent file, Maven previously printed the same error message twice in different formats:Solution
1. Print usage when no goals and no POM are present
Override
postCommands()inMavenInvokerto detect the following narrow condition:-f).When both are true, print the same help output as
mvn -hand exit with code 0.If a POM is found, Maven proceeds as before: the default goal (if any) is executed, or
NoGoalSpecifiedExceptionis reported as today. Existing behavior for all normal project builds is unchanged.2. Clean up the
-fmissing-file error messageWhen
getTopDirectory()throws anIllegalArgumentExceptionbecause the-f/--fileargument points to a non-existent path, the exception message is already self-explanatory ("POM file X does not exist"). It is now logged directly instead of being wrapped in the opaque "Error determining top directory" prefix and then repeated as a cause chain. The output is now:Why this approach
mvn.cmd,mvnDebug, etc.determinePom()which is a cheap file-existence check viaModelProcessor.locateExistingPom(). No parent POM downloads, no DI warmup.postCommands()fires afterlookup()(DI is ready,context.lookupis available), sodeterminePom()can be called safely.mvn -hconvention.