grpc/grpc-java · error · RuntimeException
Cannot load EpollSocketChannel
Error message
Cannot load EpollSocketChannel
What it means
gRPC-netty tries to load io.netty.channel.epoll.EpollSocketChannel via reflection to support epoll transport on Linux. This RuntimeException wraps the ClassNotFoundException raised when the netty-transport-native-epoll artifact (or its epoll native binding) is not on the classpath. It means the code path requiring epoll was entered but the epoll classes are absent.
Source
Thrown at netty/src/main/java/io/grpc/netty/Utils.java:400
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 {
Class<? extends Channel> channelType = Class
.forName("io.netty.channel.epoll.EpollSocketChannel").asSubclass(Channel.class);
return channelType;
} catch (ClassNotFoundException e) {
throw new RuntimeException("Cannot load EpollSocketChannel", e);
}
}
// Must call when epoll is available
private static Class<? extends Channel> epollDomainSocketChannelType() {
try {
Class<? extends Channel> channelType = Class
.forName("io.netty.channel.epoll.EpollDomainSocketChannel").asSubclass(Channel.class);
return channelType;
} catch (ClassNotFoundException e) {
throw new RuntimeException("Cannot load EpollDomainSocketChannel", e);
}
}
// Must call when epoll is available
private static Constructor<? extends EventLoopGroup> epollEventLoopGroupConstructor() {
try {
return ClassView on GitHub (pinned to 64daddc1f3)
Solutions
- Add the dependency io.netty:netty-transport-native-epoll with the linux-x86_64 (or relevant) classifier matching your grpc-netty version
- Verify the Netty version on the classpath matches the one grpc-netty expects (mvn dependency:tree); align versions with the netty-bom
- If epoll is not needed, stop requesting the epoll channel type and let gRPC use the default NIO channel (NettyChannelBuilder defaults)
- Check that your build/packaging (shade plugin, container image) includes io/netty/channel/epoll/** classes and the native epoll .so library
Example fix
// before (pom.xml) <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-netty</artifactId> </dependency> // after <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-netty</artifactId> </dependency> <dependency> <groupId>io.netty</groupId> <artifactId>netty-transport-native-epoll</artifactId> <classifier>linux-x86_64</classifier> </dependency>
Defensive patterns
Strategy: fallback
Validate before calling
boolean epollAvailable = false;
try {
Class.forName("io.netty.channel.epoll.EpollSocketChannel");
epollAvailable = true;
} catch (ClassNotFoundException e) {
// epoll transport not on classpath
} Type guard
static boolean hasEpollTransport() {
try {
Class.forName("io.netty.channel.epoll.EpollSocketChannel");
return true;
} catch (Throwable t) {
return false;
}
} Try / catch
try {
builder.channelType(io.grpc.netty.Utils.EPOLL_CHANNEL_TYPE);
} catch (RuntimeException e) {
if (e.getCause() instanceof ClassNotFoundException) {
builder.channelType(io.netty.channel.socket.nio.NioSocketChannel.class); // fall back to NIO
} else {
throw e;
}
} Prevention
- Always include netty-transport-native-epoll with the correct OS classifier when targeting Linux epoll
- Check Utils.isEpollAvailable() (or Class.forName probe) before requesting epoll channel types
- Let NettyChannelBuilder auto-detect the transport instead of hardcoding epoll
- Keep Netty versions aligned with grpc-netty via netty-bom
- Verify shaded/docker images retain epoll classes and native .so files
When it happens
Trigger: Calling Utils.epollChannelType() (indirectly through Utils.DEFAULT_CHANNEL_TYPE / EpollSocketChannel type resolution) when grpc-netty selects the epoll transport — e.g. channelBuilder.channelType(Utils.epollChannelType()) or default epoll detection — while io.netty:netty-transport-native-epoll is missing from the runtime classpath.
Common situations: Running on Linux with an epoll transport configured but the netty-transport-native-epoll dependency excluded or not transitively pulled in; fat-jar repackaging that drops epoll natives; mismatched Netty versions where io.netty.channel.epoll classes moved; deploying to a non-Linux OS while code unconditionally requests epoll channels.
Related errors
- Cannot load EpollDomainSocketChannel
- Cannot load EpollEventLoopGroup
- EpollEventLoopGroup constructor not found
- Cannot load EpollServerSocketChannel
- Cannot create Epoll EventLoopGroup
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/32d49fec5fdd9e75.
Report an issue: GitHub.