Affects: 6.1.0-SNAPSHOT


  • Spring Version: 6.1.0-SNAPSHOT
  • JDK Version: Java 17

When I tried to run the test case, it reported this error, The stack:

Expecting actual throwable to be an instance of:
  org.springframework.web.client.ResourceAccessException
but was:
  java.lang.IllegalStateException: Timeout on blocking read for 5000000000 NANOSECONDS
    at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:127)
    at reactor.core.publisher.Mono.block(Mono.java:1738)
    at org.springframework.http.client.ReactorNettyClientRequest.executeInternal(ReactorNettyClientRequest.java:95)
    ...(150 remaining lines not displayed - this can be changed with Assertions.setMaxStackTraceElementsDisplayed)
java.lang.AssertionError: 
Expecting actual throwable to be an instance of:
  org.springframework.web.client.ResourceAccessException
but was:
  java.lang.IllegalStateException: Timeout on blocking read for 5000000000 NANOSECONDS
    at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:127)
    at reactor.core.publisher.Mono.block(Mono.java:1738)
    at org.springframework.http.client.ReactorNettyClientRequest.executeInternal(ReactorNettyClientRequest.java:95)
    ...(150 remaining lines not displayed - this can be changed with Assertions.setMaxStackTraceElementsDisplayed)
    at org.springframework.web.client.RestClientIntegrationTests.invalidDomain(RestClientIntegrationTests.java:709)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
    at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
    at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:992)
    at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:762)
    at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:276)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
    at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:992)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
    at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
    at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:276)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
    at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
    at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
    at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:276)
    at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
    at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)



RestClientIntegrationTests > invalidDomain(ClientHttpRequestFactory) > [6] Reactor Netty FAILED
    java.lang.AssertionError at RestClientIntegrationTests.java:709

Comment From: sbrannen

Please attempt to run it again.

That sounds like one of our flaky reactive tests.

In light of that, I'm closing this issue.

However, if you find that it fails repeatedly for you, please report back here with further details on your environment.

Comment From: hunjipo

In my environment, it always fails.

  • OS: Windows 11 22H2 22621.2134
  • Java: Java 17.0.7
  • CPU: AMD Ryzen 9 7945HX
  • IDEA: 2023.1.2

Comment From: sbrannen

Thanks for the feedback, @hunjipo.

It could potentially be an issue when running on MS Windows.

Someone from the team will investigate it.

Comment From: quaff

It may caused by proxy, please disable it and try again. I've encountered such exception if proxy enabled:

Expecting actual throwable to be an instance of:
  org.springframework.web.client.ResourceAccessException
but was:
  org.springframework.web.client.HttpServerErrorException$ServiceUnavailable: 503 Service Unavailable: "<h1>Domain Not Resolved</h1><p>[D]Domain Not Resolved|lookup example.invalid on 8.8.8.8:53: no such host</p>"

Comment From: hunjipo

It may caused by proxy, please disable it and try again. I've encountered such exception if proxy enabled:

Expecting actual throwable to be an instance of: org.springframework.web.client.ResourceAccessException but was: org.springframework.web.client.HttpServerErrorException$ServiceUnavailable: 503 Service Unavailable: "<h1>Domain Not Resolved</h1><p>[D]Domain Not Resolved|lookup example.invalid on 8.8.8.8:53: no such host</p>"

@quaff Thanks, this is a good direction, and I did indeed have proxy enabled at that time. However, I didn't enable the proxy today, and I also turned off the HTTP proxy in the IDEA settings. Despite this, the test case still failed. Another noteworthy point is that we are throwing a different exception.

Comment From: sdeleuze

I can reproduce time to time without a proxy the original exception reported (IllegalStateException). I am wondering if we should use blockOptional() with Optional.orElseThrow(Supplier) to throw a ResourceAccessException for the empty use case.

Comment From: rstoyanchev

It depends if we want to treat the timeout as a ResourceAccessException, essentially an I/O error. In this case the exchangeTimeout is configured at the level of the ReactorNettyClientRequestFactory, but a timeout can also occur at a lower level. So if we decide to handle it this way, then we should also handle the Reactor Netty TimeoutException for consistency.

If we simply increase the default exchangeTimeout, then the test expectations should be met.

Also note that for HTTP Interface Client we have a similar case with two levels of timeout settings, and if you configure timeouts at the HTTP client level, which are more fine-grained, then the exchangeTimeout can get in the way, and it can create confusion as described in #30248. This is why currently the HTTP Interface client does not impose a timeout by default, and instead relies on underlying client timeout values. It occurs to me that when used with RestClient users will once again hit an additional timeout. Perhaps it's worth considering leaving the exchangeTimeout not set at all by default.

Comment From: sdeleuze

After a related team discussion, we agreed that the wide range of possible different behaviors (dozens of milliseconds to dozens of seconds timeouts, some proxies and security software returning various HTTP code with different bodies, DNS behavior different across OSes) do not allow to have a reliable integration test for invalid domain, so we will just remove those.