-
Notifications
You must be signed in to change notification settings - Fork 3k
Description
Describe the bug
When utilizing Quarkus 3.20.2, the REST client successfully establishes an HTTP/2 connection to the OpenShift REST endpoint, with HTTP/2 functionality enabled through the configuration parameter quarkus.rest-client.http2=true. However, upon upgrading to Quarkus version 3.20.2.2 or subsequent releases, the identical implementation fails and gives 500 error
Expected behavior
The REST client should successfully establish a connection and retrieve data from the OpenShift API REST endpoint, maintaining the same connectivity behavior as observed in the Quarkus 3.20.2 platform version.
Actual behavior
When using Quarkus Platform 3.20.2.2 and later it is failing with below exception
Error id 7036361c-6487-471e-b74f-2faba199e1b4-2, java.io.IOException: Stream was closed (GOAWAY error code = 0)
Stack:
java.io.IOException: Stream was closed (GOAWAY error code = 0)
at org.jboss.resteasy.reactive.client.handlers.ClientSendRequestHandler$4.handle(ClientSendRequestHandler.java:402)
at org.jboss.resteasy.reactive.client.handlers.ClientSendRequestHandler$4.handle(ClientSendRequestHandler.java:393)
at io.vertx.core.impl.future.FutureImpl$2.onFailure(FutureImpl.java:117)
at io.vertx.core.impl.future.FutureImpl$ListenerArray.onFailure(FutureImpl.java:316)
at io.vertx.core.impl.future.FutureBase.emitFailure(FutureBase.java:81)
at io.vertx.core.impl.future.FutureImpl.tryFail(FutureImpl.java:278)
at io.vertx.core.http.impl.HttpClientRequestBase.fail(HttpClientRequestBase.java:186)
at io.vertx.core.http.impl.HttpClientRequestBase.handleException(HttpClientRequestBase.java:181)
at io.vertx.core.http.impl.HttpClientRequestImpl.handleException(HttpClientRequestImpl.java:90)
at io.vertx.core.http.impl.Http2ClientConnection$StreamImpl.handleException(Http2ClientConnection.java:557)
at io.vertx.core.impl.ContextImpl.emit(ContextImpl.java:342)
at io.vertx.core.impl.DuplicatedContext.emit(DuplicatedContext.java:163)
at io.vertx.core.http.impl.VertxHttp2Stream.onException(VertxHttp2Stream.java:97)
at io.vertx.core.http.impl.Http2ConnectionBase.onStreamClosed(Http2ConnectionBase.java:153)
at io.vertx.core.http.impl.VertxHttp2ConnectionHandler$1.onStreamClosed(VertxHttp2ConnectionHandler.java:93)
at io.netty.handler.codec.http2.DefaultHttp2Connection.notifyClosed(DefaultHttp2Connection.java:355)
at io.netty.handler.codec.http2.DefaultHttp2Connection$ActiveStreams.removeFromActiveStreams(DefaultHttp2Connection.java:1043)
at io.netty.handler.codec.http2.DefaultHttp2Connection$ActiveStreams.deactivate(DefaultHttp2Connection.java:999)
at io.netty.handler.codec.http2.DefaultHttp2Connection$DefaultStream.close(DefaultHttp2Connection.java:515)
at io.netty.handler.codec.http2.DefaultHttp2Connection$DefaultStream.close(DefaultHttp2Connection.java:521)
at io.netty.handler.codec.http2.Http2ConnectionHandler.doCloseStream(Http2ConnectionHandler.java:919)
at io.netty.handler.codec.http2.Http2ConnectionHandler.closeStream(Http2ConnectionHandler.java:627)
at io.netty.handler.codec.http2.Http2ConnectionHandler.closeStreamRemote(Http2ConnectionHandler.java:619)
at io.netty.handler.codec.http2.DefaultHttp2ConnectionDecoder$FrameReadListener.onDataRead(DefaultHttp2ConnectionDecoder.java:323)
at io.netty.handler.codec.http2.DefaultHttp2FrameReader.readDataFrame(DefaultHttp2FrameReader.java:409)
at io.netty.handler.codec.http2.DefaultHttp2FrameReader.processPayloadState(DefaultHttp2FrameReader.java:244)
at io.netty.handler.codec.http2.DefaultHttp2FrameReader.readFrame(DefaultHttp2FrameReader.java:164)
at io.netty.handler.codec.http2.DefaultHttp2ConnectionDecoder.decodeFrame(DefaultHttp2ConnectionDecoder.java:186)
at io.netty.handler.codec.http2.DecoratingHttp2ConnectionDecoder.decodeFrame(DecoratingHttp2ConnectionDecoder.java:61)
at io.netty.handler.codec.http2.DecoratingHttp2ConnectionDecoder.decodeFrame(DecoratingHttp2ConnectionDecoder.java:61)
at io.netty.handler.codec.http2.Http2ConnectionHandler$FrameDecoder.decode(Http2ConnectionHandler.java:391)
at io.netty.handler.codec.http2.Http2ConnectionHandler.decode(Http2ConnectionHandler.java:451)
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:530)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:469)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:290)
at io.vertx.core.http.impl.VertxHttp2ConnectionHandler.channelRead(VertxHttp2ConnectionHandler.java:405)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1519)
at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1377)
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1428)
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:530)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:469)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:290)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1357)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:868)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:796)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:732)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:658)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:998)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:1583)
* Connection #0 to host 127.0.0.1 left intact
How to Reproduce?
Reproducer (zip file attached)
Zip file contains simple Quarkus based application with one exposed REST endpoint and one REST client
Environment:
Tested with CRC (OpenShift local). The same behavior occurs on OpenShift 4.16.
How to run the reproducer:
Start OpenShift:
crc: `crc start` Or use any OpenShift 4.16 API server URL.
Wait for the cluster to be ready. If using an existing OpenShift cluster, proceed to the next step.
Start the application: `./gradlew quarkusDev`
Exercise the endpoint: `curl -v http://127.0.0.1:8080/test-openshift`
Expected (failing) result:
The request should return HTTP 500 and produce the exception trace.
How to verify with a working Quarkus version:
In gradle.properties, uncomment the lines that set the Quarkus platform version to 3.20.2.
If necessary, switch the Gradle wrapper to Gradle 8.x: in gradle-wrapper.properties, uncomment the Gradle 8.x distribution line and comment the Gradle 9.x line.
Re-run: ./gradlew quarkusDev
Call the endpoint again: curl -v http://127.0.0.1:8080/test-openshift
Expected (working) result:
The endpoint should return a JSON response.
Output of uname -a
or ver
Linux sonata 6.16.8-200.fc42.x86_64 #1 SMP PREEMPT_DYNAMIC Fri Sep 19 17:47:18 UTC 2025 x86_64 GNU/Linux
Output of java -version
java 21 2023-09-19 LTS Java(TM) SE Runtime Environment (build 21+35-LTS-2513) Java HotSpot(TM) 64-Bit Server VM (build 21+35-LTS-2513, mixed mode, sharing) sonuka@sonata:~/tools/crc$
Quarkus version or git rev
3.28.1
Build tool (ie. output of mvnw --version
or gradlew --version
)
9.1.0
Additional information
As the application works with Quarkus 3.20.2, it fails with Quarkus 3.20.2.2 and later. I discovered that the Vert.x Core JAR is causing this issue. When upgrading Quarkus to 3.20.2.2, for example, forcing the use of io.vertx:vertx-core:4.5.17 resolves the problem.