elastic/elasticsearch · error · TestClustersException

Can't create roles.yml config file from {} for {} as it does

Error message

Can't create roles.yml config file from {} for {} as it does not exist

What it means

Thrown by configureSecurity() during start() when a File added via rolesFile(from) does not exist (Files.exists false). Symmetric to the extra-config-file check, this guards the roles.yml append step so that a missing source file fails loudly instead of silently producing an incomplete roles file.

Source

Thrown at build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchNode.java:678

            logToProcessStdout("Setting up " + credentials.size() + " users");

            credentials.forEach(
                paramMap -> runElasticsearchBinScript(
                    getVersion().onOrAfter("6.3.0") ? "elasticsearch-users" : "x-pack/users",
                    paramMap.entrySet().stream().flatMap(entry -> Stream.of(entry.getKey(), entry.getValue())).toArray(String[]::new)
                )
            );

            // If we added users, then also add the standard test roles
            rolesFile(getBuildPluginFile("/roles.yml"));
        }
        if (roleFiles.isEmpty() == false) {
            logToProcessStdout("Setting up roles.yml");

            Path dst = configFile.getParent().resolve("roles.yml");
            roleFiles.forEach(from -> {
                if (Files.exists(from.toPath()) == false) {
                    throw new TestClustersException(
                        "Can't create roles.yml config file from " + from + " for " + this + " as it does not exist"
                    );
                }
                try {
                    final Path source = from.toPath();
                    final String content = Files.readString(source, StandardCharsets.UTF_8);
                    Files.writeString(dst, content + System.lineSeparator(), StandardCharsets.UTF_8, StandardOpenOption.APPEND);
                    LOGGER.info("Appended roles file {} to {}", source, dst);
                } catch (IOException e) {
                    throw new UncheckedIOException("Can't append roles file " + from + " to " + dst, e);
                }
            });
        }
    }

    private void installModules() {
        logToProcessStdout("Installing " + modules.size() + " modules");
        for (Provider<File> module : modules) {

View on GitHub (pinned to db6a809a66)

Solutions

  1. Verify the path in the message exists at start time.
  2. If generated, pass the producing task's output as a Provider so Gradle builds it first.
  3. If the failing source is the bundled /roles.yml, ensure the build-tools jar providing that resource is on the test classpath (not stripped by shading).
  4. Use an absolute or project-relative path resolved via project.layout.projectDirectory.

Example fix

// before: relative file that may not resolve
rolesFile(new File('roles/custom.yml'))
// after: project-relative, generated task output wired in
rolesFile(generateRolesTask.flatMap { it.outputFile.asFile })
Defensive patterns

Strategy: validation

Validate before calling

node.getRoleFiles().forEach(f -> {
    if (!Files.exists(f.toPath())) {
        throw new IllegalStateException("rolesFile source missing: " + f);
    }
});
// If generated, wire Provider<File> from the producing task.

Prevention

When it happens

Trigger: Calling node.rolesFile(file) with a File that is wrong, generated-too-late, outside the project tree, or missing on the CI checkout. Note configureSecurity() also auto-adds getBuildPluginFile('/roles.yml') when credentials are present; if that bundled resource is unreachable (classpath issue) the same throw fires.

Common situations: Custom roles file generated by a task not wired as a dependency. Path relative to wrong subproject. Bundled /roles.yml resource missing from the test classpath after a refactor of build-tools resources.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/03c816bd426a0ba7. Report an issue: GitHub.