{"record":{"id":"4fb4673794331ccc","repo":"grpc/grpc-java","slug":"channeloption-optionname-is-not-available","errorCode":null,"errorMessage":"ChannelOption(${optionName}) is not available","messagePattern":"ChannelOption\\((.+?)\\) is not available","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"netty/src/main/java/io/grpc/netty/Utils.java","lineNumber":482,"sourceCode":"   * Returns TCP_USER_TIMEOUT channel option for Epoll channel if Epoll is available, otherwise\n   * null.\n   */\n  @Nullable\n  static ChannelOption<Integer> maybeGetTcpUserTimeoutOption() {\n    return getEpollChannelOption(\"TCP_USER_TIMEOUT\");\n  }\n\n  @Nullable\n  @SuppressWarnings(\"unchecked\")\n  private static <T> ChannelOption<T> getEpollChannelOption(String optionName) {\n    if (isEpollAvailable()) {\n      try {\n        return\n            (ChannelOption<T>) Class.forName(\"io.netty.channel.epoll.EpollChannelOption\")\n                .getField(optionName)\n                .get(null);\n      } catch (Exception e) {\n        throw new RuntimeException(\"ChannelOption(\" + optionName + \") is not available\", e);\n      }\n    }\n    return null;\n  }\n\n  private static final class DefaultEventLoopGroupResource implements Resource<EventLoopGroup> {\n    private final String name;\n    private final int numEventLoops;\n    private final EventLoopGroupType eventLoopGroupType;\n\n    DefaultEventLoopGroupResource(\n        int numEventLoops, String name, EventLoopGroupType eventLoopGroupType) {\n      this.name = name;\n      // See the implementation of MultithreadEventLoopGroup.  DEFAULT_EVENT_LOOP_THREADS there\n      // defaults to NettyRuntime.availableProcessors() * 2.  We don't think we need that many\n      // threads.  The overhead of a thread includes file descriptors and at least one chunk\n      // allocation from PooledByteBufAllocator.  Here we reduce the default number of threads by\n      // half.","sourceCodeStart":464,"sourceCodeEnd":500,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/netty/src/main/java/io/grpc/netty/Utils.java#L464-L500","documentation":"Utils.getEpollChannelOption reflectively reads a static ChannelOption field (e.g. EpollChannelOption.TCP_USER_TIMEOUT) from io.netty.channel.epoll.EpollChannelOption. If the class exists but the field lookup or access fails (missing in the Netty version, or access error), the exception is wrapped and rethrown with this message. It signals an incompatibility between the requested epoll channel option and the Netty version on the classpath.","triggerScenarios":"grpc-netty calls maybeGetTcpUserTimeoutOption (e.g. when enableCheckEffectiveTcpUserTimeout / user timeout config is used) on a Netty version where EpollChannelOption lacks the requested field, or field access is blocked; only happens on epoll path on Linux.","commonSituations":"Netty version too old to define TCP_USER_TIMEOUT in EpollChannelOption; shaded/relocated Netty classes so the reflection target isn't the expected class; security manager or module restrictions blocking getField().get(null).","solutions":["Upgrade Netty (netty-transport-native-epoll) to a version that defines the requested EpollChannelOption field (e.g. TCP_USER_TIMEOUT, Netty 4.1.x recent)","Align grpc-netty's transitive Netty version explicitly with your Netty dependencies to avoid shading/mixing versions","Avoid enabling the option that requires the lookup (e.g. don't set tcp user timeout) if your Netty version lacks it","Use NIO channel types so the epoll option lookup path is skipped"],"exampleFix":"// before (pom.xml)\n<dependency><groupId>io.netty</groupId><artifactId>netty-transport-native-epoll</artifactId><version>4.1.30.Final</version></dependency>\n// after\n<dependency><groupId>io.netty</groupId><artifactId>netty-transport-native-epoll</artifactId><version>4.1.100.Final</version><classifier>linux-x86_64</classifier></dependency>","handlingStrategy":"validation","validationCode":"boolean tcpUserTimeoutSupported;\ntry {\n  Class.forName(\"io.netty.channel.epoll.EpollChannelOption\").getField(\"TCP_USER_TIMEOUT\");\n  tcpUserTimeoutSupported = true;\n} catch (ReflectiveOperationException e) { tcpUserTimeoutSupported = false; }","typeGuard":null,"tryCatchPattern":"try {\n  channel = builder.build();\n} catch (RuntimeException e) {\n  if (e.getMessage() != null && e.getMessage().startsWith(\"ChannelOption(\")) {\n    // downgrade: drop the option / use NIO and retry\n    channel = builder.channelType(NioSocketChannel.class).build();\n  } else { throw e; }\n}","preventionTips":["Pin a Netty version new enough for the epoll options grpc-netty expects","Avoid mixing shaded/relocated Netty classes with grpc-netty","Feature-detect channel options instead of assuming TCP_USER_TIMEOUT exists","Keep grpc-netty and netty versions upgraded together"],"tags":["netty","epoll","reflection","channel-option","version-incompatibility"],"backgroundTag":"class-not-found","analyzedSha":"64daddc1f3d1975670f769f3e97bde8b2ba32d25","analyzedAt":"2026-09-08T06:14:57.704Z","contentChangedAt":"2026-09-08T06:14:57.704Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}