grpc/grpc-java · error · RuntimeException
Cannot load EpollDomainSocketChannel
Error message
Cannot load EpollDomainSocketChannel
What it means
gRPC-netty loads io.netty.channel.epoll.EpollDomainSocketChannel reflectively to support Unix domain socket channels. This RuntimeException wraps the ClassNotFoundException raised when the epoll transport classes are not on the classpath. The caller is expected to invoke this only when epoll is available, so failing here means the epoll dependency is missing despite that assumption.
Source
Thrown at netty/src/main/java/io/grpc/netty/Utils.java:411
// 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 Class
.forName("io.netty.channel.epoll.EpollEventLoopGroup").asSubclass(EventLoopGroup.class)
.getConstructor(Integer.TYPE, ThreadFactory.class);
} catch (ClassNotFoundException e) {
throw new RuntimeException("Cannot load EpollEventLoopGroup", e);
} catch (NoSuchMethodException e) {
throw new RuntimeException("EpollEventLoopGroup constructor not found", e);
}
}
// Must call when epoll is available
private static Class<? extends ServerChannel> epollServerChannelType() {View on GitHub (pinned to 64daddc1f3)
Solutions
- Add io.netty:netty-transport-native-epoll with the appropriate linux classifier to the runtime classpath
- Confirm the UDS address is only used on Linux with epoll support present; otherwise fall back to TCP/loopback
- Align Netty versions (dependency:tree) so io.netty.channel.epoll.EpollDomainSocketChannel exists at the expected version
- Check packaging rules (shade excludes, jlink, image slimming) are not stripping io.netty.channel.epoll.* or the native .so
Example fix
// before
ManagedChannel ch = NettyChannelBuilder.forAddress("unix", "/var/run/srv.sock").build(); // throws if epoll missing
// after — ensure classpath has:
// implementation 'io.netty:netty-transport-native-epoll:4.1.x:linux-x86_64'
ManagedChannel ch = NettyChannelBuilder.forAddress("unix", "/var/run/srv.sock")
.channelType(io.grpc.netty.Utils.EPOLL_DOMAIN_SOCKET_CHANNEL_TYPE)
.build(); Defensive patterns
Strategy: fallback
Validate before calling
static boolean epollDomainSocketSupported() {
try {
Class.forName("io.netty.channel.epoll.EpollDomainSocketChannel");
return true;
} catch (ClassNotFoundException e) {
return false;
}
} Type guard
static boolean canUseUnixDomainSocket() {
return "Linux".equalsIgnoreCase(System.getProperty("os.name")) && epollDomainSocketSupported();
} Try / catch
try {
return NettyChannelBuilder.forAddress("unix", sockPath);
} catch (RuntimeException e) {
if (e.getCause() instanceof ClassNotFoundException) {
return NettyChannelBuilder.forAddress("localhost", tcpPort); // fall back to TCP
}
throw e;
} Prevention
- Ship netty-transport-native-epoll when using unix: targets
- Probe for EpollDomainSocketChannel before choosing UDS transport
- Fall back to TCP loopback on non-Linux or when epoll natives are missing
- Keep Netty version consistent with grpc-netty
- Test UDS channels in the same packaging used in production
When it happens
Trigger: Resolving the domain socket channel type via Utils.epollDomainSocketChannelType() (used when the target address is a unix:/// UDS address) while io.netty:netty-transport-native-epoll is absent from the runtime classpath.
Common situations: Connecting to a server over a Unix domain socket (NettyChannelBuilder.forAddress(UnixDomainSocketAddress...) or 'unix:' target) on Linux without the netty-transport-native-epoll dependency; slimmed container images or shaded jars that omit the epoll classes/natives.
Related errors
- Cannot load EpollSocketChannel
- Cannot load EpollEventLoopGroup
- Cannot load EpollServerSocketChannel
- OkHttpChannelBuilder not found on the classpath
- Exception while checking Epoll availability
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/4a17e302f21856c4.
Report an issue: GitHub.