apache/maven · error · ToolchainFactoryException

Non-existing JDK home configuration at

Error message

Non-existing JDK home configuration at 

What it means

DefaultJavaToolchainFactory validates that the path given in <jdkHome> exists on the filesystem before accepting the toolchain. Paths.get(value).normalize() is checked with Files.exists; a path that does not resolve to an existing directory throws ToolchainFactoryException with the absolute path in the message. Note that existence is checked from the machine running Maven, not the machine that wrote the file.

Source

Thrown at impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultJavaToolchainFactory.java:86

                    String key = entry.getKey();
                    String value = entry.getValue();
                    if (value == null) {
                        throw new ToolchainFactoryException(
                                "Provides token '" + key + "' doesn't have any value configured.");
                    }
                    return "version".equals(key) ? new VersionMatcher(versionParser, value) : new ExactMatcher(value);
                }));

        // compute and normalize the java home
        XmlNode dom = model.getConfiguration();
        XmlNode javahome = dom != null ? dom.child(KEY_JAVAHOME) : null;
        if (javahome == null || javahome.value() == null) {
            throw new ToolchainFactoryException(
                    "Java toolchain without the " + KEY_JAVAHOME + " configuration element.");
        }
        Path normal = Paths.get(javahome.value()).normalize();
        if (!Files.exists(normal)) {
            throw new ToolchainFactoryException("Non-existing JDK home configuration at " + normal.toAbsolutePath());
        }
        String javaHome = normal.toString();

        Version javaVersion = model.getProvides().entrySet().stream()
                .filter(entry -> "version".equals(entry.getKey()))
                .map(Map.Entry::getValue)
                .map(versionParser::parseVersion)
                .findAny()
                .orElse(null);

        return new DefaultJavaToolchain(model, javaHome, javaVersion, matchers);
    }

    @Nonnull
    @Override
    public Optional<Toolchain> createDefaultToolchain() {
        return Optional.empty();
    }

View on GitHub (pinned to e4093d4e12)

Solutions

  1. Correct jdkHome to an existing JDK directory on this machine (verify with ls /path)
  2. Use environment-relative setup: JAVA_HOME-based toolchain discovery or keep per-machine toolchains.xml in ~/.m2 instead of committing it
  3. On CI, install the expected JDK at the documented path or generate toolchains.xml in the pipeline

Example fix

<!-- before -->
<jdkHome>/usr/lib/jvm/java-17-openjdk</jdkHome> <!-- removed by upgrade -->

<!-- after -->
<jdkHome>/usr/lib/jvm/java-21-openjdk</jdkHome>
Defensive patterns

Strategy: validation

Validate before calling

String home = jdkHome.value();
if (!Files.isDirectory(Paths.get(home))) {
    throw new IllegalArgumentException('jdkHome does not exist on this machine: ' + home);
}

Prevention

When it happens

Trigger: toolchains.xml pointing to a JDK location that is absent on the current machine: /usr/lib/jvm/java-17 on a host where the JDK was upgraded/removed, or a developer-specific path (C:\Users\alice\...) used by another developer or CI runner.

Common situations: Team-committed or copied toolchains.xml with machine-specific paths; macOS JDK version bump invalidating /Library/Java/JavaVirtualMachines/...; container images where the JDK lives at a different prefix; symlinks removed after OS updates; typo in the path.

Related errors


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