grpc/grpc-java · error · RuntimeException
Exception while checking Epoll availability
Error message
Exception while checking Epoll availability
What it means
Utils.isEpollAvailable() reflectively invokes io.netty.channel.epoll.Epoll.isAvailable(). ClassNotFoundException (epoll jar absent) is treated as "not available", but any other reflective failure is rethrown as an unchecked RuntimeException "Exception while checking Epoll availability". This indicates the epoll probe itself broke, not merely that epoll is unavailable.
Source
Thrown at netty/src/main/java/io/grpc/netty/Utils.java:377
if (t instanceof Http2Exception) {
return Status.INTERNAL.withDescription("http2 exception").withCause(t);
}
return s;
}
@VisibleForTesting
static boolean isEpollAvailable() {
try {
return (boolean) (Boolean)
Class
.forName("io.netty.channel.epoll.Epoll")
.getDeclaredMethod("isAvailable")
.invoke(null);
} catch (ClassNotFoundException e) {
// this is normal if netty-epoll runtime dependency doesn't exist.
return false;
} catch (Exception e) {
throw new RuntimeException("Exception while checking Epoll availability", e);
}
}
private static Throwable getEpollUnavailabilityCause() {
try {
return (Throwable)
Class
.forName("io.netty.channel.epoll.Epoll")
.getDeclaredMethod("unavailabilityCause")
.invoke(null);
} catch (Exception e) {
return e;
}
}
// Must call when epoll is available
private static Class<? extends Channel> epollChannelType() {
try {View on GitHub (pinned to 64daddc1f3)
Solutions
- Read the cause: it reveals whether native library loading failed or reflection was blocked.
- Add the correct netty-transport-native-epoll artifact for your OS/arch (or the `netty-transport-native-epoll` with linux-x86_64 classifier) matching your netty version.
- Fix packaging so native .so files survive shading/fat-jar assembly, or disable epoll by using NIO (default) instead of forcing epoll.
- If running on non-Linux, use the default NIO transport rather than EpollChannelType.
- Call Epoll.isAvailable()/Epoll.autoDetection() semantics first and fall back to NIO when unavailable.
Example fix
// before
if (Utils.isEpollAvailable()) { ... } // throws when native lib is broken
// after
if (Epoll.isAvailable()) {
channelType = EpollDomainSocket/EpollSocketChannel; // native present
} else {
channelType = NioSocketChannel; // safe fallback
} Defensive patterns
Strategy: fallback
Validate before calling
boolean epollUsable = io.netty.channel.epoll.Epoll.isAvailable(); // no exception: returns false when jar/native missing
Class<? extends io.netty.channel.Channel> channelType = epollUsable
? io.netty.channel.epoll.EpollSocketChannel
: io.netty.channel.nio.NioSocketChannel; Type guard
static boolean epollSafeToUse() {
try {
return Utils.isEpollAvailable();
} catch (RuntimeException e) {
return false; // treat broken epoll probe as unavailable
}
} Try / catch
try {
useEpoll();
} catch (RuntimeException e) {
if (e.getMessage().contains("Epoll availability")) {
useNio(); // fall back to JDK NIO transport
}
} Prevention
- Always check Epoll.isAvailable() before selecting epoll channel types
- Include netty-transport-native-epoll with the right OS classifier for your platform
- Verify native .so files survive shading/fat-jar packaging
- Fall back to NIO on non-Linux or when natives are absent
When it happens
Trigger: Calling isEpollAvailable() (directly or via Utils/EpollChannelOption setup on Linux) when reflective invocation of Epoll.isAvailable() throws — e.g. the native epoll library failed to load (UnsatisfiedLinkError wrapped in ExceptionInInitializerError), SecurityManager blocking reflection, or a corrupted/partial netty-transport-native-epoll installation.
Common situations: Deploying grpc-netty without the matching netty-transport-native-epoll classifier jar (wrong OS/arch classifier); Alpine/musl images without the glibc epoll native build; fat jars excluding native .so files; running on non-Linux with code paths that assume epoll and mishandle the exception.
Understand the failure class
Background: "X is not installed. Please install it with pip install Y": missing optional dependency errors — ImportError/ValueError raised when a library's optional extra was never installed — this error's family across 22 libraries.
Related errors
- Cannot create Epoll EventLoopGroup
- Cannot load EpollSocketChannel
- Cannot load EpollDomainSocketChannel
- Cannot load EpollEventLoopGroup
- EpollEventLoopGroup constructor not found
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/218b007f7b1a00b3.
Report an issue: GitHub.