elastic/elasticsearch · error · TestClustersException

Failed to set the keystore password for

Error message

Failed to set the keystore password for {}

What it means

Thrown by startElasticsearchProcess() when Files.writeString(esInputFile, keystorePassword+'\n', CREATE) raises an IOException, wrapped as TestClustersException with the node identity. The code writes the keystore password to a temp file so it can be fed to the ES process via processBuilder.redirectInput; failing to materialise that file means the secured keystore cannot be unlocked at boot.

Solutions

  1. Read the cause IOException for the precise FS error (message vs permission vs space).
  2. Clean build/testclusters/<node> so esInputFile and its parent are recreated.
  3. Free disk / inodes and fix ownership on the build dir.
  4. Shorten the build path on Windows to avoid MAX_PATH for the input file.
Defensive patterns

Strategy: try-catch

Validate before calling

// Confirm the esInputFile parent is writable before start
Path inputParent = node.getEsInputFile().getParent();
if (Files.exists(inputParent) && !Files.isWritable(inputParent)) {
    throw new IllegalStateException("esInputFile dir not writable: " + inputParent);
}
if (node.getKeystorePassword() != null && node.getKeystorePassword().length() > 0
        && OS.current() == OS.WINDOWS && node.getEsInputFile().toString().length() > 240) {
    throw new IllegalStateException("esInputFile path too long for Windows: " + node.getEsInputFile());
}

Try / catch

try {
    node.start();
} catch (TestClustersException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Failed to set the keystore password")) {
        throw new IllegalStateException("Keystore password file write failed (disk/perms/path): "
            + e.getCause(), e);
    }
    throw e;
}

Prevention

When it happens

Trigger: A non-empty keystorePassword is configured, and writing it to esInputFile fails: parent dir missing/ read-only, disk full, permission residue, path-too-long, or antivirus interference. The check fires at process launch time inside start().

Common situations: Disk full on CI agent. Permission residue from a root-owned prior run. Windows MAX_PATH in the esInputFile path. Antivirus locking temp files. Stale build/testclusters after a host change.

Related errors


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

Appendix: source

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

        processBuilder.directory(workingDir.toFile());
        Map<String, String> environment = processBuilder.environment();
        // Don't inherit anything from the environment for as that would lack reproducibility
        environment.clear();
        environment.putAll(getESEnvironment());
        String cliJvmArgsString = String.join(" ", cliJvmArgs);
        environment.put("CLI_JAVA_OPTS", cliJvmArgsString + " " + System.getProperty("tests.jvm.argline", ""));

        // Direct the stderr to the ES log file. This should capture any jvm problems to start.
        // Stdout is discarded because ES duplicates the log file to stdout when run in the foreground.
        processBuilder.redirectOutput(ProcessBuilder.Redirect.appendTo(esOutputFile.toFile()));
        processBuilder.redirectErrorStream(true);

        if (keystorePassword != null && keystorePassword.length() > 0) {
            try {
                Files.writeString(esInputFile, keystorePassword + "\n", StandardOpenOption.CREATE);
                processBuilder.redirectInput(esInputFile.toFile());
            } catch (IOException e) {
                throw new TestClustersException("Failed to set the keystore password for " + this, e);
            }
        }
        LOGGER.info("Running `{}` in `{}` for {} env: {}", command, workingDir, this, environment);
        Process esProcess;
        try {
            esProcess = processBuilder.start();
        } catch (IOException e) {
            throw new TestClustersException("Failed to start ES process for " + this, e);
        }
        testClustersRegistryProvider.get().storeProcess(id(), esProcess);
        reaperServiceProvider.get().registerPid(toString(), esProcess.pid());
    }

    @Internal
    public Path getDistroDir() {
        return canUseSharedDistribution()
            ? getExtractedDistributionDir().toFile().listFiles()[0].toPath()
            : workingDir.resolve("distro").resolve(getVersion() + "-" + testDistribution);

View on GitHub (pinned to db6a809a66)