elastic/elasticsearch · error · TestClustersException
supplied keystore file {} does not exist, require for {}
Error message
supplied keystore file {} does not exist, require for {} What it means
Thrown during start() after keystore files are registered but before invoking elasticsearch-keystore add-file. The code requires a non-null File (requireNonNull) AND that file.exists() is true; a missing source file aborts keystore provisioning. This protects the keystore command from being handed a nonexistent path, which would otherwise surface as an opaque CLI error.
Source
Thrown at build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchNode.java:542
}
logToProcessStdout("Creating elasticsearch keystore with password set to [" + keystorePassword + "]");
if (keystorePassword.length() > 0) {
runElasticsearchBinScriptWithInput(keystorePassword + "\n" + keystorePassword, "elasticsearch-keystore", "create", "-p");
} else {
runElasticsearchBinScript("elasticsearch-keystore", "-v", "create");
}
if (keystoreSettings.isEmpty() == false || keystoreFiles.isEmpty() == false) {
logToProcessStdout("Adding " + keystoreSettings.size() + " keystore settings and " + keystoreFiles.size() + " keystore files");
keystoreSettings.forEach((key, value) -> runKeystoreCommandWithPassword(keystorePassword, value.toString(), "add", key));
for (Map.Entry<String, File> entry : keystoreFiles.entrySet()) {
File file = entry.getValue();
requireNonNull(file, "supplied keystoreFile was null when configuring " + this);
if (file.exists() == false) {
throw new TestClustersException("supplied keystore file " + file + " does not exist, require for " + this);
}
runKeystoreCommandWithPassword(keystorePassword, "", "add-file", entry.getKey(), file.getAbsolutePath());
}
}
installModules();
if (isSettingTrue("xpack.security.enabled")) {
if (credentials.isEmpty()) {
user(Collections.emptyMap());
}
}
configureSecurity();
if (cliSetup.isEmpty() == false) {
logToProcessStdout("Running " + cliSetup.size() + " setup commands");
View on GitHub (pinned to db6a809a66)
Solutions
- Verify the path printed in the message exists on disk at the time the test cluster starts: ls -la <path>.
- If the file is generated by another task, wire it through a Provider/FileCollection so Gradle creates the task dependency, e.g. keystoreFile('my.setting', generateKeyTask.flatMap { it.outputFile }).
- If it is a checked-in resource, confirm it is committed and (for git-lfs) pulled on the CI agent.
- Use an absolute path or resolve via project.layout.projectDirectory.file(...) to avoid working-directory ambiguity.
Example fix
// before: static file path that may not exist
keystoreFile('bootstrap.password', new File('certs/key.txt'))
// after: wire a task output as a provider so it exists before start
keystoreFile('bootstrap.password', generateKeyTask.flatMap { it.outputFile.asFile }) Defensive patterns
Strategy: validation
Validate before calling
// Validate keystore files exist before starting
node.getKeystoreFiles().forEach((k, f) -> {
requireNonNull(f, "keystoreFile null for key " + k);
if (!f.exists()) {
throw new IllegalStateException("keystoreFile missing for key " + k + ": " + f);
}
});
// Prefer wiring task outputs as providers so Gradle builds them before start(). Prevention
- Wire generated keystore material through Provider<File> task outputs, not static Files.
- Commit checked-in key material (or pull git-lfs on CI).
- Resolve paths via project.layout.projectDirectory.file(...) to avoid working-dir ambiguity.
When it happens
Trigger: Calling keystoreFile(settingKey, file) with a File whose path is wrong, generated by a task that has not produced it yet, located outside the Gradle project root, or resolved relative to the wrong working directory. Because LazyPropertyMap is lazy, the existence check fires at start() time, not at registration time.
Common situations: Referencing a generated file (cert, key material) whose producing task was not declared as an input dependency of the test cluster. Typo in the path. File created in a different subproject's build dir. Resource path resolved against the wrong project. CI checked out without large files / git-lfs objects.
Related errors
- Can't create roles.yml config file from {} for {} as it does
- Can't create extra config file from {} for {} as it does not
- Can't append roles file {} to {}
- extra config file destination can't be relative, was {} for
- Unknown keys in user definition {} for {}
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/414358343e539582.
Report an issue: GitHub.