apache/maven · error · FileNotFoundException

The specified user toolchains file does not exist: {}

Error message

The specified user toolchains file does not exist: {}

What it means

The -t / --toolchains option points Maven at a user toolchains file. MavenCli.toolchains() resolves the given path via ResolveFile.resolveFile() against the current working directory (making absolute paths out of relative ones) and requires the result to be an existing regular file. If File.isFile() is false it throws FileNotFoundException with the resolved path embedded, before any build starts.

Source

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

                if (!hint.equals(SettingsXmlConfigurationProcessor.HINT)) {
                    ConfigurationProcessor configurationProcessor = entry.getValue();
                    sb.append(String.format(
                            "%s%n", configurationProcessor.getClass().getName()));
                }
            }
            throw new Exception(sb.toString());
        }
    }

    void toolchains(CliRequest cliRequest) throws Exception {
        File userToolchainsFile = null;

        if (cliRequest.commandLine.hasOption(CLIManager.ALTERNATE_USER_TOOLCHAINS)) {
            userToolchainsFile = new File(cliRequest.commandLine.getOptionValue(CLIManager.ALTERNATE_USER_TOOLCHAINS));
            userToolchainsFile = ResolveFile.resolveFile(userToolchainsFile, cliRequest.workingDirectory);

            if (!userToolchainsFile.isFile()) {
                throw new FileNotFoundException(
                        "The specified user toolchains file does not exist: " + userToolchainsFile);
            }
        } else {
            String userToolchainsFileStr = cliRequest.getUserProperties().getProperty(Constants.MAVEN_USER_TOOLCHAINS);
            if (userToolchainsFileStr != null) {
                userToolchainsFile = new File(userToolchainsFileStr);
            }
        }

        File installationToolchainsFile = null;

        if (cliRequest.commandLine.hasOption(CLIManager.ALTERNATE_INSTALLATION_TOOLCHAINS)) {
            installationToolchainsFile =
                    new File(cliRequest.commandLine.getOptionValue(CLIManager.ALTERNATE_INSTALLATION_TOOLCHAINS));
            installationToolchainsFile =
                    ResolveFile.resolveFile(installationToolchainsFile, cliRequest.workingDirectory);

            if (!installationToolchainsFile.isFile()) {

View on GitHub (pinned to e4093d4e12)

Solutions

  1. Check the path printed in the message — it is already resolved against the working directory, so verify with ls <printed-path>.
  2. Use an absolute path (or ${session.rootDirectory}/... style anchoring) instead of a relative one when the build may start from a different cwd.
  3. In CI, make sure the toolchains file is created/downloaded before the mvn -t step and persists into that step's workspace.
  4. If you do not need a toolchains file, drop the -t option entirely and rely on the default ~/.m2/toolchains.xml.

Example fix

# before (relative path, wrong cwd)
mvn -t toolchains/jdk.xml package

# after (absolute path)
mvn -t "$PWD/toolchains/jdk.xml" package
Defensive patterns

Strategy: validation

Validate before calling

// Java launcher, before doMain
String tcPath = argAfter(args, "-t", "--toolchains");
if (tcPath != null) {
    Path p = Path.of(workingDir).resolve(tcPath).normalize();
    if (!Files.isRegularFile(p)) {
        throw new FileNotFoundException("Toolchains file missing, refusing to start mvn: " + p);
    }
}

Try / catch

try {
    mavenCli.doMain(args, ...);
} catch (FileNotFoundException e) {
    if (e.getMessage() != null && e.getMessage().contains("toolchains file does not exist")) {
        // report resolved path + cwd, regenerate or fix -t value
    }
    throw e;
}

Prevention

When it happens

Trigger: mvn -t toolchains.xml when toolchains.xml is absent from the working directory. Relative paths that resolve against a different cwd (CI steps that cd between checkout and build). Passing a directory, a symlink to a missing target, or a path with a typo. Values injected via wrapper scripts (-t ${TOOLCHAINS_FILE} with the variable empty or wrong).

Common situations: CI pipelines that generate the toolchains file in one stage but run mvn -t in another stage/directory where the file was not carried over. Developers switching branches where the file is gitignored locally. Jobs moved between agents with different home layouts while using ~/.m2/toolchains.xml-style relative references.

Related errors


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