apache/maven · error · ExitException

Directory {} extracted from the -f/--file command-line argum

Error message

Directory {} extracted from the -f/--file command-line argument {} does not exist

What it means

While pre-scanning raw arguments for -f/--file, MavenCli resolves the value against the current top directory. If the value is an existing regular file (a POM), its parent directory becomes the new top directory; when that parent then fails Files.isDirectory (concurrently removed, a dangling symlink used as the file's parent, or a permission-denied stat), 'Directory <parent> extracted from the -f/--file command-line argument <arg> does not exist' is printed and ExitException stops startup with code 1.

Source

Thrown at compat/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java:371

        }

        // We need to locate the top level project which may be pointed at using
        // the -f/--file option.  However, the command line isn't parsed yet, so
        // we need to iterate through the args to find it and act upon it.
        Path topDirectory = fileSystem.getPath(cliRequest.workingDirectory);
        boolean isAltFile = false;
        for (String arg : cliRequest.args) {
            if (isAltFile) {
                // this is the argument following -f/--file
                Path path = topDirectory.resolve(stripLeadingAndTrailingQuotes(arg));
                if (Files.isDirectory(path)) {
                    topDirectory = path;
                } else if (Files.isRegularFile(path)) {
                    topDirectory = path.getParent();
                    if (!Files.isDirectory(topDirectory)) {
                        System.err.println("Directory " + topDirectory
                                + " extracted from the -f/--file command-line argument " + arg + " does not exist");
                        throw new ExitException(1);
                    }
                } else {
                    System.err.println(
                            "POM file " + arg + " specified with the -f/--file command line argument does not exist");
                    throw new ExitException(1);
                }
                break;
            } else {
                // Check if this is the -f/--file option
                isAltFile = arg.equals("-f") || arg.equals("--file");
            }
        }
        topDirectory = getCanonicalPath(topDirectory);
        cliRequest.topDirectory = topDirectory;
        // We're very early in the process, and we don't have the container set up yet,
        // so we rely on the JDK services to eventually look up a custom RootLocator.
        // This is used to compute {@code session.rootDirectory} but all {@code project.rootDirectory}
        // properties will be computed through the RootLocator found in the container.

View on GitHub (pinned to e4093d4e12)

Solutions

  1. Re-run with the parent directory itself: mvn -f /real/parent/dir (Maven will find pom.xml there)
  2. Replace symlinked intermediate directories in the -f path with the real path (readlink -f to canonicalize)
  3. Verify with ls -la that every path segment of the -f argument is a real directory
  4. If a script deletes/recreates the module directory, ensure it completes before mvn starts

Example fix

# before: 'build' is a dangling symlink
mvn -f ./build/pom.xml

# after: use the real directory
mvn -f /workspace/modules/app
Defensive patterns

Strategy: validation

Validate before calling

import java.nio.file.*;

// pre-check a -f argument before invoking Maven
Path arg = Paths.get(fValue).toRealPath(); // throws if any symlink is broken
Path topDir = Files.isDirectory(arg) ? arg : arg.getParent();
if (!Files.isDirectory(topDir)) {
    throw new IllegalArgumentException("-f argument parent is not a usable directory: " + topDir);
}

Try / catch

catch (ExitException e) {
    if (stderrCapture.contains("extracted from the -f/--file command-line argument")) {
        // pass the parent directory itself instead of the pom path and retry once
        retryWithArguments(replaceArgument(args, fValue, topDirectoryAsString));
    }
}

Prevention

When it happens

Trigger: mvn -f <pom> where <pom> resolves to a regular file but its parent directory is not a usable directory at check time — parent symlink chain broken, directory deleted between the two checks, or unusual filesystems (some network/FUSE mounts) where isDirectory on the parent fails.

Common situations: Pointing -f at a path through a symlinked directory whose target was moved; build scripts racing with directory cleanup; container mounts where the parent directory is present in the image but masked at runtime.

Related errors


AI-assisted analysis of apache/maven@e4093d4e12 (2026-08-21). Data as JSON: /api/errors/471fdb3a65af504f. Report an issue: GitHub.