Skip to content

WebClient throws "Only one connection receive subscriber allowed." when response generates a WebClientResponseException [SPR-17576] #22108

Closed
@spring-projects-issues

Description

@spring-projects-issues

Kyle Cronin opened SPR-17576 and commented

Noticed this error while upgrading spring boot from 2.0.0 to 2.1.1 and was able to reproduce with a simple test created through start.spring.io. This seems to be similar to #22014 that was fixed in 5.1.3, but the error occurs regardless of "Content-Type" header and or body content. The sample project is attached.

package com.example.webclienttest;

import static org.junit.Assert.assertEquals;

import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClientResponseException;

@RunWith(SpringRunner.class)
@SpringBootTest
public class WebclienttestApplicationTests {

	private MockWebServer server = new MockWebServer();

	@After
	public void tearDown() throws Exception {
		server.shutdown();
	}

	@Test
	public void clientTest() {
		MockResponse response = new MockResponse();
		response.setResponseCode(400)
				.setHeader("Content-Type", MediaType.TEXT_PLAIN)
				.setBody("bar");
		this.server.enqueue(response);
		WebClient client = WebClient.builder().baseUrl(server.url("/").toString()).build();
		try {
			client.get().uri("foo")
					.retrieve()
					.bodyToMono(String.class)
					.block();
		} catch (WebClientResponseException e) {
			assertEquals(HttpStatus.BAD_REQUEST, e.getStatusCode());
		}
	}
}

The test passes but in the console you will notice the following log event:

2018-12-06 12:56:10.349 ERROR 53024 --- [ctor-http-nio-4] reactor.core.publisher.Operators         : Operator called default onErrorDropped

java.lang.IllegalStateException: Only one connection receive subscriber allowed.
	at reactor.netty.channel.FluxReceive.startReceiver(FluxReceive.java:277) [reactor-netty-0.8.3.RELEASE.jar:0.8.3.RELEASE]
	at reactor.netty.channel.FluxReceive.subscribe(FluxReceive.java:127) [reactor-netty-0.8.3.RELEASE.jar:0.8.3.RELEASE]
	at reactor.core.publisher.FluxMap.subscribe(FluxMap.java:62) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.netty.ByteBufFlux.subscribe(ByteBufFlux.java:290) [reactor-netty-0.8.3.RELEASE.jar:0.8.3.RELEASE]
	at reactor.core.publisher.FluxPeek.subscribe(FluxPeek.java:83) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.FluxMap.subscribe(FluxMap.java:62) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.FluxMap.subscribe(FluxMap.java:62) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.FluxOnErrorResume.subscribe(FluxOnErrorResume.java:47) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.MonoIgnoreElements.subscribe(MonoIgnoreElements.java:37) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.Mono.subscribe(Mono.java:3608) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:172) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.MonoOnErrorResume.subscribe(MonoOnErrorResume.java:44) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.Mono.subscribe(Mono.java:3608) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:172) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.Mono.subscribe(Mono.java:3608) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:97) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.secondError(MonoFlatMap.java:185) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.MonoFlatMap$FlatMapInner.onError(MonoFlatMap.java:251) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.Operators$MonoSubscriber.onError(Operators.java:1521) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreInner.onError(MonoIgnoreThen.java:235) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:100) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.Operators.error(Operators.java:181) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.MonoError.subscribe(MonoError.java:52) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.Mono.subscribe(Mono.java:3608) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:97) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.Operators$MonoSubscriber.onError(Operators.java:1521) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreInner.onError(MonoIgnoreThen.java:235) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.MonoIgnoreElements$IgnoreElementsSubscriber.onError(MonoIgnoreElements.java:76) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:100) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.Operators.error(Operators.java:181) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.FluxError.subscribe(FluxError.java:43) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.Flux.subscribe(Flux.java:7734) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:97) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.FluxMap$MapSubscriber.onError(FluxMap.java:126) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.FluxMap$MapSubscriber.onError(FluxMap.java:126) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.Operators.error(Operators.java:181) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.FluxPeek$PeekSubscriber.onSubscribe(FluxPeek.java:157) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.FluxMap$MapSubscriber.onSubscribe(FluxMap.java:86) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.Operators.error(Operators.java:180) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.netty.channel.FluxReceive.startReceiver(FluxReceive.java:277) [reactor-netty-0.8.3.RELEASE.jar:0.8.3.RELEASE]
	at reactor.netty.channel.FluxReceive.subscribe(FluxReceive.java:127) [reactor-netty-0.8.3.RELEASE.jar:0.8.3.RELEASE]
	at reactor.core.publisher.FluxMap.subscribe(FluxMap.java:62) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.netty.ByteBufFlux.subscribe(ByteBufFlux.java:290) [reactor-netty-0.8.3.RELEASE.jar:0.8.3.RELEASE]
	at reactor.core.publisher.FluxPeek.subscribe(FluxPeek.java:83) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.FluxMap.subscribe(FluxMap.java:62) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.FluxMap.subscribe(FluxMap.java:62) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.FluxOnErrorResume.subscribe(FluxOnErrorResume.java:47) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.MonoIgnoreElements.subscribe(MonoIgnoreElements.java:37) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.Mono.subscribe(Mono.java:3608) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:172) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.MonoOnErrorResume.subscribe(MonoOnErrorResume.java:44) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.Mono.subscribe(Mono.java:3608) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:172) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:150) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:114) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.FluxDefaultIfEmpty$DefaultIfEmptySubscriber.onNext(FluxDefaultIfEmpty.java:92) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:121) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.FluxContextStart$ContextStartSubscriber.onNext(FluxContextStart.java:103) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.FluxMapFuseable$MapFuseableConditionalSubscriber.onNext(FluxMapFuseable.java:287) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.FluxFilterFuseable$FilterFuseableConditionalSubscriber.onNext(FluxFilterFuseable.java:331) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1476) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.MonoCollectList$MonoBufferAllSubscriber.onComplete(MonoCollectList.java:118) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:136) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:252) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:136) [reactor-core-3.2.3.RELEASE.jar:3.2.3.RELEASE]
	at reactor.netty.channel.FluxReceive.terminateReceiver(FluxReceive.java:378) [reactor-netty-0.8.3.RELEASE.jar:0.8.3.RELEASE]
	at reactor.netty.channel.FluxReceive.drainReceiver(FluxReceive.java:202) [reactor-netty-0.8.3.RELEASE.jar:0.8.3.RELEASE]
	at reactor.netty.channel.FluxReceive.onInboundComplete(FluxReceive.java:343) [reactor-netty-0.8.3.RELEASE.jar:0.8.3.RELEASE]
	at reactor.netty.channel.ChannelOperations.onInboundComplete(ChannelOperations.java:325) [reactor-netty-0.8.3.RELEASE.jar:0.8.3.RELEASE]
	at reactor.netty.channel.ChannelOperations.terminate(ChannelOperations.java:372) [reactor-netty-0.8.3.RELEASE.jar:0.8.3.RELEASE]
	at reactor.netty.http.client.HttpClientOperations.onInboundNext(HttpClientOperations.java:511) [reactor-netty-0.8.3.RELEASE.jar:0.8.3.RELEASE]
	at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:141) [reactor-netty-0.8.3.RELEASE.jar:0.8.3.RELEASE]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) [netty-transport-4.1.31.Final.jar:4.1.31.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) [netty-transport-4.1.31.Final.jar:4.1.31.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) [netty-transport-4.1.31.Final.jar:4.1.31.Final]
	at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102) [netty-codec-4.1.31.Final.jar:4.1.31.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) [netty-transport-4.1.31.Final.jar:4.1.31.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) [netty-transport-4.1.31.Final.jar:4.1.31.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) [netty-transport-4.1.31.Final.jar:4.1.31.Final]
	at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:438) [netty-transport-4.1.31.Final.jar:4.1.31.Final]
	at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:323) [netty-codec-4.1.31.Final.jar:4.1.31.Final]
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:297) [netty-codec-4.1.31.Final.jar:4.1.31.Final]
	at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:253) [netty-transport-4.1.31.Final.jar:4.1.31.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) [netty-transport-4.1.31.Final.jar:4.1.31.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) [netty-transport-4.1.31.Final.jar:4.1.31.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) [netty-transport-4.1.31.Final.jar:4.1.31.Final]
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1434) [netty-transport-4.1.31.Final.jar:4.1.31.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) [netty-transport-4.1.31.Final.jar:4.1.31.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) [netty-transport-4.1.31.Final.jar:4.1.31.Final]
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:965) [netty-transport-4.1.31.Final.jar:4.1.31.Final]
	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163) [netty-transport-4.1.31.Final.jar:4.1.31.Final]
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:648) [netty-transport-4.1.31.Final.jar:4.1.31.Final]
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:583) [netty-transport-4.1.31.Final.jar:4.1.31.Final]
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:500) [netty-transport-4.1.31.Final.jar:4.1.31.Final]
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:462) [netty-transport-4.1.31.Final.jar:4.1.31.Final]
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:897) [netty-common-4.1.31.Final.jar:4.1.31.Final]
	at java.lang.Thread.run(Thread.java:748) [na:1.8.0_181]

Affects: 5.1.3

Attachments:

Issue Links:

Metadata

Metadata

Assignees

Labels

in: webIssues in web modules (web, webmvc, webflux, websocket)status: duplicateA duplicate of another issue

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions