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

  1. Check permissions: `ls -la $ES_HOME/lib/entitlement-bridge/` as the elasticsearch user.
  2. Fix ownership: `chown -R elasticsearch:elasticsearch $ES_HOME`.
  3. Inspect dmesg / OS logs for filesystem errors; on NFS, remount or use a local volume.
  4. 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

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


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