{"record":{"id":"4625f24e57758633","repo":"apache/maven","slug":"provides-token-key-doesn-t-have-any-valu-4625f2","errorCode":null,"errorMessage":"Provides token '\" + key + \"' doesn't have any value configured.","messagePattern":"Provides token '\" \\+ key \\+ \"' doesn't have any value configured\\.","errorType":"validation","errorClass":"ToolchainFactoryException","httpStatus":null,"severity":"error","filePath":"impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultJavaToolchainFactory.java","lineNumber":71,"sourceCode":"    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultJavaToolchainFactory.class);\n\n    final VersionParser versionParser;\n\n    @Inject\n    public DefaultJavaToolchainFactory(VersionParser versionParser) {\n        this.versionParser = versionParser;\n    }\n\n    @Nonnull\n    @Override\n    public JavaToolchain createToolchain(@Nonnull ToolchainModel model) {\n        // populate the provides section\n        Map<String, Predicate<String>> matchers = model.getProvides().entrySet().stream()\n                .collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, entry -> {\n                    String key = entry.getKey();\n                    String value = entry.getValue();\n                    if (value == null) {\n                        throw new ToolchainFactoryException(\n                                \"Provides token '\" + key + \"' doesn't have any value configured.\");\n                    }\n                    return \"version\".equals(key) ? new VersionMatcher(versionParser, value) : new ExactMatcher(value);\n                }));\n\n        // compute and normalize the java home\n        XmlNode dom = model.getConfiguration();\n        XmlNode javahome = dom != null ? dom.child(KEY_JAVAHOME) : null;\n        if (javahome == null || javahome.value() == null) {\n            throw new ToolchainFactoryException(\n                    \"Java toolchain without the \" + KEY_JAVAHOME + \" configuration element.\");\n        }\n        Path normal = Paths.get(javahome.value()).normalize();\n        if (!Files.exists(normal)) {\n            throw new ToolchainFactoryException(\"Non-existing JDK home configuration at \" + normal.toAbsolutePath());\n        }\n        String javaHome = normal.toString();\n","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/apache/maven/blob/e4093d4e120eac99d6bdce5ba67cace2f3085c97/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultJavaToolchainFactory.java#L53-L89","documentation":"DefaultJavaToolchainFactory.createToolchain builds matchers from the <provides> section of a toolchain declaration in toolchains.xml. Every provides token must map to a non-null string value; an entry with a null value throws ToolchainFactoryException. This is a declarative configuration error caught when the toolchain is built, before any JDK is used.","triggerScenarios":"A ~/.m2/toolchains.xml <toolchain> block where <provides> contains an element with empty content that the model parses as null, e.g. <provides><version/></provides> or a token defined only as an attribute placeholder without a body.","commonSituations":"Hand-edited toolchains.xml with self-closed or empty provides tokens; templates that inject provides values from environment variables that resolve to nothing; XML with the value accidentally placed in an attribute instead of element text.","solutions":["Give every <provides> token a text value, e.g. <provides><version>17</version><vendor>temurin</vendor></provides>","Check for self-closing tags (<token/>) and stray attribute-style values in toolchains.xml and convert them to element text","If the token is not needed, delete it entirely rather than leaving it empty"],"exampleFix":"<!-- before -->\n<toolchain>\n  <type>jdk</type>\n  <provides>\n    <version/>\n  </provides>\n  <configuration><jdkHome>/usr/lib/jvm/java-17</jdkHome></configuration>\n</toolchain>\n\n<!-- after -->\n<toolchain>\n  <type>jdk</type>\n  <provides>\n    <version>17</version>\n  </provides>\n  <configuration><jdkHome>/usr/lib/jvm/java-17</jdkHome></configuration>\n</toolchain>","handlingStrategy":"validation","validationCode":"for (Map.Entry<String, String> e : model.getProvides().entrySet()) {\n    if (e.getValue() == null || e.getValue().isBlank()) {\n        throw new IllegalArgumentException('Toolchain provides token without value: ' + e.getKey());\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Lint toolchains.xml for empty/self-closed provides elements","Fail fast with the token name before calling createToolchain","Provide values for every token you declare"],"tags":["maven","toolchains","configuration","jdk"],"backgroundTag":"toolchain-misconfiguration","analyzedSha":"e4093d4e120eac99d6bdce5ba67cace2f3085c97","analyzedAt":"2026-08-21T22:58:24.034Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}