elastic/elasticsearch · critical · IllegalStateException
Directory for entitlement bridge jar does not exist: ${dir}
Error message
Directory for entitlement bridge jar does not exist: ${dir} What it means
Thrown by SystemJvmOptions.attachEntitlementAgent when the `lib/entitlement-bridge` directory under ES_HOME does not exist. The entitlement bridge is a JVM agent jar that instruments JDK classes to enforce Elasticsearch's runtime entitlement policy; without it the node cannot enforce file/network/process entitlements. The error is an IllegalStateException because a shipped distribution should always contain this directory — its absence indicates a broken or tampered installation.
Source
Thrown at distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/SystemJvmOptions.java:164
return enableNativeAccessOptions.stream();
}
/*
* Only affects 22 and 22.0.1, see https://bugs.openjdk.org/browse/JDK-8329528
*/
@UpdateForV10(owner = UpdateForV10.Owner.CORE_INFRA) // This could be removed when min JDK version = 25
private static Stream<String> maybeWorkaroundG1Bug() {
Runtime.Version v = Runtime.version();
if (v.feature() == 22 && v.update() <= 1) {
return Stream.of("-XX:+UnlockDiagnosticVMOptions", "-XX:G1NumCollectionsKeepPinned=10000000");
}
return Stream.of();
}
private static Stream<String> attachEntitlementAgent(Path esHome) {
Path dir = esHome.resolve("lib/entitlement-bridge");
if (Files.exists(dir) == false) {
throw new IllegalStateException("Directory for entitlement bridge jar does not exist: " + dir);
}
String bridgeJar;
try (var s = Files.list(dir)) {
var candidates = s.limit(2).toList();
if (candidates.size() != 1) {
throw new IllegalStateException("Expected one jar in " + dir + "; found " + candidates.size());
}
bridgeJar = candidates.get(0).toString();
} catch (IOException e) {
throw new IllegalStateException("Failed to list entitlement jars in: " + dir, e);
}
// We instrument classes in these modules to call the bridge. Because the bridge gets patched
// into java.base, we must export the bridge from java.base to these modules, as a comma-separated list
String modulesContainingEntitlementInstrumentation =
"java.logging,java.net.http,java.naming,jdk.net,jdk.zipfs,jdk.management.agent";
return Stream.of(
"-XX:+EnableDynamicAgentLoading",View on GitHub (pinned to db6a809a66)
Solutions
- Confirm ES_HOME points at a complete, freshly extracted distribution: `ls $ES_HOME/lib/entitlement-bridge/`.
- Re-extract or reinstall the distribution from an official artifact.
- If building from source, run the full distribution build (e.g. `./gradlew :distribution:archives:linux-tar:assemble`) and run from the assembled archive, not the source tree.
- Verify no startup script or Dockerfile is deleting lib/entitlement-bridge.
Example fix
# before ES_HOME=/path/to/partial-extract # after ES_HOME=/path/to/full-elasticsearch-9.0.0 ls $ES_HOME/lib/entitlement-bridge # should list exactly one jar
Defensive patterns
Strategy: validation
Validate before calling
Path bridge = esHome.resolve("lib/entitlement-bridge");
if (!Files.isDirectory(bridge)) {
throw new IllegalStateException("Missing entitlement-bridge directory at " + bridge + "; reinstall the distribution.");
} Type guard
static boolean hasEntitlementBridge(Path esHome) {
return Files.isDirectory(esHome.resolve("lib/entitlement-bridge"));
} Try / catch
try {
List<String> opts = SystemJvmOptions.forEnv(env).getAsArguments();
} catch (IllegalStateException e) {
if (e.getMessage().contains("entitlement bridge")) {
// halt deployment; alert ops that the distribution is incomplete
} else throw e;
} Prevention
- Extract distributions into a fresh directory per version rather than overlaying.
- After extraction, run a smoke check listing lib/entitlement-bridge before starting the node.
- In Docker images, COPY the whole distribution and assert the bridge dir exists in a build-time RUN step.
When it happens
Trigger: Running Elasticsearch from a partial extraction of the distribution tarball/zip. A custom distribution that does not stage the entitlement-bridge jar. ES_HOME pointing at the wrong directory (e.g. the source tree rather than a built distribution). Deleting lib/entitlement-bridge manually.
Common situations: Operators copy only a subset of files when deploying. CI images built from a truncated `gradlew distribution:zip` output. Source-tree development where the dev runs `bin/elasticsearch` against an unbuilt layout.
Related errors
- Expected one jar in ${dir}; found ${candidates.size()}
- Failed to list entitlement jars in: ${dir}
- starting java failed with [%d] output: %s error: %s
- USAGE
- Unknown secure settings source [${source}]
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/60cfd0524fac1e9a.
Report an issue: GitHub.