quarkusio/quarkus · error · UnsupportedOperationException
io_uring is not supported with Netty 4.2
Error message
io_uring is not supported with Netty 4.2
What it means
Pulsar's native-image substitutions stub out the legacy Netty io_uring incubator classes because they are incompatible with Netty 4.2. At native runtime, if the legacy IOUringEventLoop is somehow instantiated and its run() executes, it throws UnsupportedOperationException instead of doing real io_uring work.
Source
Thrown at extensions/smallrye-reactive-messaging-pulsar/runtime/src/main/java/io/quarkus/pulsar/runtime/graal/PulsarSubstitutions.java:20
import com.oracle.svm.core.annotate.Substitute;
import com.oracle.svm.core.annotate.TargetClass;
/**
* Pulsar 4.2.x depends on netty-incubator-transport-native-io_uring:0.0.26.Final
* which was compiled against Netty 4.1.x. Netty 4.2 removed
* {@code PlatformDependent.getIntVolatile(long)} causing native image linking
* failures. These substitutions replace the methods that reference the missing
* API so GraalVM can link the io_uring classes. The substituted methods are
* never called at runtime because io_uring is opt-in
* ({@code -Dpulsar.enableUring=true}) and Linux-only.
*/
@TargetClass(className = "io.netty.incubator.channel.uring.IOUringEventLoop")
final class Target_IOUringEventLoop {
@Substitute
protected void run() {
throw new UnsupportedOperationException("io_uring is not supported with Netty 4.2");
}
@Substitute
protected void cleanup() {
throw new UnsupportedOperationException("io_uring is not supported with Netty 4.2");
}
}
@TargetClass(className = "io.netty.incubator.channel.uring.Native")
final class Target_IOUringNative {
@Substitute
static Target_RingBuffer createRingBuffer(int ringSize) {
throw new UnsupportedOperationException("io_uring is not supported with Netty 4.2");
}
@Substitute
static Target_RingBuffer createRingBuffer(int ringSize, int flags) {View on GitHub (pinned to e1c734241f)
Solutions
- Remove the netty-transport-native-epoll/io_uring-incubator legacy wiring and let Netty 4.2's built-in io_uring (io.netty.transport.io_uring) be used
- Drop explicit IOUringEventLoopGroup / preferNative selection from client config
- Pin Netty to 4.1.x if the incubator io_uring transport is strictly required
Example fix
// before EventLoopGroup group = new IOUringEventLoopGroup(); // after EventLoopGroup group = new NioEventLoopGroup(); // or Netty 4.2 io_uring transport
Defensive patterns
Strategy: fallback
Validate before calling
// Detect legacy io_uring incubator usage at startup
Class.forName("io.netty.incubator.channel.uring.IOUringEventLoop");
if (isNativeImage() && nettyVersion() != null && nettyVersion().startsWith("4.2")) {
log.warn("Legacy io_uring incubator detected with Netty 4.2 in native mode; falling back to NIO");
} Try / catch
try {
eventLoopGroup = new IOUringEventLoopGroup();
} catch (Throwable t) {
if (t instanceof UnsupportedOperationException) {
eventLoopGroup = new NioEventLoopGroup();
} else {
throw t;
}
} Prevention
- Do not add the netty io_uring incubator dependency when building with Netty 4.2
- Avoid -Dio.netty.transport.preferNative=true unless the supported 4.2 io_uring transport is used
- Test native builds after any Netty version upgrade
When it happens
Trigger: Running a Pulsar-client application as a native image with Netty 4.2 on the classpath while code explicitly selects the io_uring event loop (e.g. -Dio.netty.transport.preferNative=true or explicit IOUringEventLoopGroup usage).
Common situations: Migrating Pulsar apps to Netty 4.2 where the old io_uring incubator dependency is still present and still referenced by transport configuration.
Related errors
- Could not find Jetty NPN/ALPN or Conscrypt as installed JDK
- Unsupported provider: ${provider}
- Unsupported compressor in native mode
- Unix socket not supported
- OCSP is not supported with this SslProvider:
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/4a52c79754a90feb.
Report an issue: GitHub.