apache/maven · error · IllegalStateException

Unable to find the root directory. Create a .mvn directory i

Error message

Unable to find the root directory. Create a .mvn directory in the root directory or add the root="true" attribute on the root project's model to identify it.

What it means

RootLocator walks up from a directory looking for the project root: a directory containing .mvn or a model carrying root="true". findMandatoryRoot throws IllegalStateException (this message, also the UNABLE_TO_FIND_ROOT_PROJECT_MESSAGE constant) when no ancestor up to the filesystem root qualifies.

Source

Thrown at compat/maven-model-builder/src/main/java/org/apache/maven/model/root/RootLocator.java:51

 *
 * The default implementation will look for a {@code .mvn} child directory
 * or a {@code pom.xml} containing the {@code root="true"} attribute.
 *
 * @see DefaultRootLocator
 * @deprecated use {@code org.apache.maven.api.services.model.RootLocator} instead
 */
@Deprecated(since = "4.0.0")
public interface RootLocator {

    String UNABLE_TO_FIND_ROOT_PROJECT_MESSAGE = "Unable to find the root directory. "
            + "Create a .mvn directory in the root directory or add the root=\"true\""
            + " attribute on the root project's model to identify it.";

    @Nonnull
    default Path findMandatoryRoot(Path basedir) {
        Path rootDirectory = findRoot(basedir);
        if (rootDirectory == null) {
            throw new IllegalStateException(getNoRootMessage());
        }
        return rootDirectory;
    }

    @Nullable
    default Path findRoot(Path basedir) {
        Path rootDirectory = basedir;
        while (rootDirectory != null && !isRootDirectory(rootDirectory)) {
            rootDirectory = rootDirectory.getParent();
        }
        return rootDirectory;
    }

    @Nonnull
    default String getNoRootMessage() {
        return UNABLE_TO_FIND_ROOT_PROJECT_MESSAGE;
    }

View on GitHub (pinned to e4093d4e12)

Solutions

  1. Create a .mvn directory in the project root: mkdir -p /path/to/project/.mvn (an empty one is enough)
  2. Or mark the root model (model 4.0.0+): <project root="true">
  3. Run the build from inside the project tree so basedir is below the root
  4. Customize detection by implementing RootLocator.isRootDirectory/getNoRootMessage instead of suppressing the exception

Example fix

# before: no marker anywhere above the build directory
mvn -f /tmp/checkout/module-a/pom.xml verify

# after: mark the root once (either works)
mkdir -p /tmp/checkout/.mvn
# or, with model 4.0.0+:
#   <project root="true"> in /tmp/checkout/pom.xml
Defensive patterns

Strategy: validation

Validate before calling

// Check for a root before calling the mandatory variant
Path root = locator.findRoot(basedir);
if (root == null) {
    throw new IllegalStateException(
        "No .mvn directory above " + basedir + "; create it or set root=\"true\" on the root model");
}
Path mandatory = locator.findMandatoryRoot(basedir);

Type guard

static boolean isProjectRoot(Path dir) {
    return Files.isDirectory(dir.resolve(".mvn"));
}

Prevention

When it happens

Trigger: Calling findMandatoryRoot(basedir) directly or via tooling that requires a session root directory (MavenSession.getRootDirectory and friends) on a tree that has no .mvn directory and no root="true" model anywhere above basedir.

Common situations: Running root-aware tooling on a bare directory; zip/tar exports that dropped dotfiles including .mvn; CI checkouts with dotfile exclusion rules; multi-module trees where .mvn was never committed.

Related errors


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