quarkusio/quarkus · error · RuntimeException

Should be virtual server channel:

Error message

Should be virtual server channel: 

What it means

VirtualClientConnection.connect() looks up a server-side channel registered in VirtualChannelRegistry for the given remote address and requires it to be a VirtualServerChannel. If the bound object is a different Channel implementation, the registry contents are inconsistent with the virtual transport's expectations, so a RuntimeException is thrown naming the offending class.

Source

Thrown at extensions/netty/runtime/src/main/java/io/quarkus/netty/runtime/virtual/VirtualClientConnection.java:120

    /**
     * Establish a virtual intra-JVM connection
     *
     * @param remoteAddress
     * @param clientAddress
     * @return
     */
    public static VirtualClientConnection connect(VirtualResponseHandler handler, VirtualAddress remoteAddress,
            SocketAddress clientAddress) {
        if (clientAddress == null)
            clientAddress = remoteAddress;

        Channel boundChannel = VirtualChannelRegistry.get(remoteAddress);
        if (boundChannel == null) {
            throw new RuntimeException("No virtual channel available");
        }
        if (!(boundChannel instanceof VirtualServerChannel)) {
            throw new RuntimeException("Should be virtual server channel: " + boundChannel.getClass().getName());
        }

        VirtualServerChannel serverChannel = (VirtualServerChannel) boundChannel;
        VirtualClientConnection conn = new VirtualClientConnection(clientAddress, handler);
        conn.peer = serverChannel.serve(conn);
        return conn;
    }
}

View on GitHub (pinned to e1c734241f)

Solutions

  1. Ensure the address bound in VirtualChannelRegistry was created via VirtualServerChannel bind/registration, not a client channel
  2. Inspect the class name in the message to find what actually got registered under that address
  3. Clear or reset VirtualChannelRegistry between tests so stale client channels are not reused

Example fix

// before
VirtualChannelRegistry.register(remoteAddress, someVirtualClientChannel);
// after
VirtualServerChannel server = ...; // create via virtual server bootstrap
server.bind(remoteAddress).sync();
VirtualClientConnection.connect(bootstrap, remoteAddress, clientAddress, handler);
Defensive patterns

Strategy: validation

Validate before calling

Channel boundChannel = VirtualChannelRegistry.get(remoteAddress);
if (!(boundChannel instanceof VirtualServerChannel)) {
    throw new IllegalStateException("Address not bound to a VirtualServerChannel: " + remoteAddress);
}

Type guard

static boolean isVirtualServerBound(SocketAddress addr) {
    Channel ch = VirtualChannelRegistry.get(addr);
    return ch instanceof VirtualServerChannel;
}

Try / catch

try {
    VirtualClientConnection conn = VirtualClientConnection.connect(bootstrap, remoteAddress, clientAddress, handler);
} catch (RuntimeException e) {
    if (e.getMessage().startsWith("Should be virtual server channel")) { /* re-register correct server channel */ }
}

Prevention

When it happens

Trigger: Calling VirtualClientConnection.connect(...) with a remoteAddress that maps in VirtualChannelRegistry to a Channel that is not a VirtualServerChannel (e.g. a VirtualClientChannel or a real Netty channel registered under the same address).

Common situations: Tests or custom code registering the wrong channel type in VirtualChannelRegistry; reusing an address that was bound by a client connection rather than a VirtualServerChannel.bind(); stale registry entries across test cases.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/c166e892bf2d5fa9. Report an issue: GitHub.