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 Class

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Add the dependency io.netty:netty-transport-native-epoll with the linux-x86_64 (or relevant) classifier matching your grpc-netty version
  2. Verify the Netty version on the classpath matches the one grpc-netty expects (mvn dependency:tree); align versions with the netty-bom
  3. If epoll is not needed, stop requesting the epoll channel type and let gRPC use the default NIO channel (NettyChannelBuilder defaults)
  4. 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

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


AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08). Data as JSON: /api/errors/32d49fec5fdd9e75. Report an issue: GitHub.