apache/maven · error · ToolchainFactoryException

Java toolchain without the jdkHome configuration element.

Error message

Java toolchain without the jdkHome configuration element.

What it means

When building a JDK toolchain, DefaultJavaToolchainFactory requires a <jdkHome> child element inside the toolchain's <configuration> block in toolchains.xml. If configuration is missing entirely, or has no jdkHome element, or the element has no text value, creation fails with ToolchainFactoryException. jdkHome is the only mandatory configuration element for the jdk toolchain type.

Source

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

    @Override
    public JavaToolchain createToolchain(@Nonnull ToolchainModel model) {
        // populate the provides section
        Map<String, Predicate<String>> matchers = model.getProvides().entrySet().stream()
                .collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, entry -> {
                    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);
    }

View on GitHub (pinned to e4093d4e12)

Solutions

  1. Add <configuration><jdkHome>/path/to/jdk</jdkHome></configuration> inside the jdk toolchain element
  2. Verify the element name is exactly jdkHome (case-sensitive) with a non-empty text value
  3. Replace unexpanded ${...} placeholders with a literal path or ensure the property is available when toolchains.xml is read

Example fix

<!-- before -->
<toolchain>
  <type>jdk</type>
  <provides><version>17</version></provides>
  <configuration/>
</toolchain>

<!-- after -->
<toolchain>
  <type>jdk</type>
  <provides><version>17</version></provides>
  <configuration>
    <jdkHome>/usr/lib/jvm/temurin-17</jdkHome>
  </configuration>
</toolchain>
Defensive patterns

Strategy: validation

Validate before calling

XmlNode cfg = model.getConfiguration();
XmlNode jdkHome = cfg != null ? cfg.child('jdkHome') : null;
if (jdkHome == null || jdkHome.value() == null || jdkHome.value().isBlank()) {
    throw new IllegalArgumentException('jdk toolchain requires <configuration><jdkHome>...</jdkHome></configuration>');
}

Prevention

When it happens

Trigger: A toolchains.xml <toolchain><type>jdk</type> entry with an empty <configuration/>, a misspelled element like <javaHome> or <jdk>, or a jdkHome element whose value comes from an unexpanded property leaving it empty.

Common situations: First-time toolchains.xml setup following outdated docs that use different element names; property placeholders (${env.JAVA_HOME}) not being interpolated in toolchains.xml; copying a .NET-style or custom toolchain template; Maven 3 to 4 migrations where the file was never completed.

Related errors


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