quarkusio/quarkus · error · RuntimeException
No virtual channel available
Error message
No virtual channel available
What it means
VirtualClientConnection.connect looks up the remote address in VirtualChannelRegistry to find a bound server channel. If no virtual channel is registered under that remote address, a RuntimeException("No virtual channel available") is thrown — the virtual-transport equivalent of 'connection refused': nothing is listening at that address.
Source
Thrown at extensions/netty/runtime/src/main/java/io/quarkus/netty/runtime/virtual/VirtualClientConnection.java:117
public static VirtualClientConnection connect(VirtualResponseHandler handler, VirtualAddress remoteAddress) {
return connect(handler, remoteAddress, remoteAddress);
}
/**
* 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
- Ensure the virtual server channel is bound and still active before the client connects (await bind().sync() and check registry).
- Use the exact VirtualAddress instance returned by the server's bind for the client's remote address.
- Close connections before shutting the server down; keep server lifetime scoped around client usage.
- Add retry/await logic (e.g. Awaitility) for the registry entry to appear in concurrent tests.
Example fix
// before VirtualClientConnection.connect(channel, peer, remoteAddress); // server not bound yet -> throws // after serverChannel.bind(localAddr).syncUninterruptibly(); // guarantee bound first await().atMost(2, SECONDS).until(() -> VirtualChannelRegistry.get(localAddr) != null); VirtualClientConnection.connect(channel, peer, localAddr);
Defensive patterns
Strategy: retry
Validate before calling
if (VirtualChannelRegistry.get(remoteAddress) == null) {
throw new IllegalStateException("no virtual server bound at " + remoteAddress + "; bind the server first");
} Try / catch
try {
VirtualClientConnection.connect(channel, peer, remoteAddress);
} catch (RuntimeException e) {
if ("No virtual channel available".equals(e.getMessage())) {
await().atMost(2, SECONDS).until(() -> VirtualChannelRegistry.get(remoteAddress) != null);
VirtualClientConnection.connect(channel, peer, remoteAddress);
} else { throw e; }
} Prevention
- Always await the server's bind completion before clients connect
- Reuse the exact VirtualAddress instance returned from the bind for the client's remote address
- Order shutdown: close client connections before the server channel
- In tests, poll the registry (Awaitility) instead of connecting immediately
When it happens
Trigger: Connecting a virtual client to a remote VirtualAddress that no server channel has bound; connecting before the server finished binding; address typo/mismatch between the bound VirtualAddress and the connect target; server channel closed (unregistered) before the client connects.
Common situations: In-memory client/server test setups where the client connect races the server bind; tests restarted without rebinding; using raw SocketAddress values that don't match the registered VirtualAddress instance; teardown ordering shutting down the server first.
Related errors
- already bound
- unsupported address type:
- address already in use by:
- IOException(e)
- Could not find Jetty NPN/ALPN or Conscrypt as installed JDK
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/b15aaf3b8a998e2c.
Report an issue: GitHub.