elastic/elasticsearch · critical · IllegalStateException
Failed to list entitlement jars in: ${dir}
Error message
Failed to list entitlement jars in: ${dir} What it means
Thrown by SystemJvmOptions.attachEntitlementAgent when `Files.list(dir)` raises an IOException while enumerating the entitlement-bridge directory. The original IOException is wrapped in an IllegalStateException with the directory path as context. Unlike the existence and count checks, this is an OS-level I/O failure: the directory may exist but be unreadable due to permissions, race conditions (directory removed mid-listing), or filesystem errors (NFS stale handle, disk failure).
Source
Thrown at distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/SystemJvmOptions.java:174
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",
"-Djdk.attach.allowAttachSelf=true",
"--patch-module=java.base=" + bridgeJar,
"--add-exports=java.base/org.elasticsearch.entitlement.bridge=org.elasticsearch.entitlement,"
+ modulesContainingEntitlementInstrumentation
);
}
}
View on GitHub (pinned to db6a809a66)
Solutions
- Check permissions: `ls -la $ES_HOME/lib/entitlement-bridge/` as the elasticsearch user.
- Fix ownership: `chown -R elasticsearch:elasticsearch $ES_HOME`.
- Inspect dmesg / OS logs for filesystem errors; on NFS, remount or use a local volume.
- On SELinux systems, run `restorecon -R $ES_HOME` and check audit logs for denials.
Example fix
# before $ id; ls $ES_HOME/lib/entitlement-bridge/ ls: cannot open directory: Permission denied # after sudo chown -R elasticsearch:elasticsearch $ES_HOME sudo -u elasticsearch ls $ES_HOME/lib/entitlement-bridge/
Defensive patterns
Strategy: try-catch
Validate before calling
Path bridge = esHome.resolve("lib/entitlement-bridge");
if (!Files.isReadable(bridge)) {
throw new IllegalStateException("Cannot read " + bridge + "; check ownership and SELinux/AppArmor.");
} Type guard
static boolean isReadableDir(Path p) {
return Files.isDirectory(p) && Files.isReadable(p);
} Try / catch
try (var s = Files.list(bridge)) {
// ...
} catch (IOException e) {
// surface the directory path, check perms, log the OS errno, and rethrow as IllegalStateException
throw new IllegalStateException("Failed to list entitlement jars in: " + bridge, e);
} Prevention
- Run `chown -R elasticsearch:elasticsearch $ES_HOME` after extraction.
- On SELinux hosts, `restorecon -R $ES_HOME` and check `audit.log`.
- Validate directory readability as part of a preflight script before launch.
When it happens
Trigger: Running Elasticsearch as a user without read permission on lib/entitlement-bridge. A concurrent process deletes the directory between the exists check and the list call. NFS or container overlay filesystem returning EIO. SELinux/AppArmor denying directory read.
Common situations: Wrong ownership on the distribution files (e.g. extracted as root, run as elasticsearch user without chown). Container securityContext using readOnlyRootFilesystem without granting read to lib. NFS mount glitches.
Related errors
- Failed to list entitlement jars in: {}
- Failed to create parent directory '%s' when creating directo
- Failed to create directory '%s'
- Failed to list existing plugins
- Directory for entitlement bridge jar does not exist: ${dir}
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/9151ba52487b3b8d.
Report an issue: GitHub.