Skip to content

@RequestBody raises IllegalStateException for form data #22486

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
kichewko-giga opened this issue Feb 27, 2019 · 2 comments
Closed

@RequestBody raises IllegalStateException for form data #22486

kichewko-giga opened this issue Feb 27, 2019 · 2 comments
Assignees
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: enhancement A general enhancement
Milestone

Comments

@kichewko-giga
Copy link

kichewko-giga commented Feb 27, 2019

Affects: Spring Boot 2.1.3.RELEASE


Hello!

I noticed something interesting. When you make a mistake in WebFlux application, you don't see real exception, instead you see the same exception every-time:

2019-02-27 16:41:41.686 ERROR 28059 --- [or-http-epoll-1] a.w.r.e.AbstractErrorWebExceptionHandler : [2af64f7c] 500 Server Error for HTTP POST "/hello"

java.lang.IllegalStateException: Only one connection receive subscriber allowed.
        at reactor.netty.channel.FluxReceive.startReceiver(FluxReceive.java:271) ~[reactor-netty-0.8.5.RELEASE.jar:0.8.5.RELEASE]
        at reactor.netty.channel.FluxReceive.subscribe(FluxReceive.java:121) ~[reactor-netty-0.8.5.RELEASE.jar:0.8.5.RELEASE]
        at reactor.core.publisher.FluxMap.subscribe(FluxMap.java:62) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxOnAssembly.subscribe(FluxOnAssembly.java:132) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.netty.ByteBufFlux.subscribe(ByteBufFlux.java:294) ~[reactor-netty-0.8.5.RELEASE.jar:0.8.5.RELEASE]
        at reactor.core.publisher.FluxPeek.subscribe(FluxPeek.java:83) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxOnAssembly.subscribe(FluxOnAssembly.java:132) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.netty.ByteBufFlux.subscribe(ByteBufFlux.java:294) ~[reactor-netty-0.8.5.RELEASE.jar:0.8.5.RELEASE]
        at reactor.core.publisher.FluxMap.subscribe(FluxMap.java:62) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxOnAssembly.subscribe(FluxOnAssembly.java:132) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoCollectList.subscribe(MonoCollectList.java:59) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:56) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoFilterFuseable.subscribe(MonoFilterFuseable.java:44) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:56) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoMapFuseable.subscribe(MonoMapFuseable.java:56) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:56) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
...

Example controller:

package app.controllers;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloWorld {

    @PostMapping("/hello")
    public String handle(@RequestBody String body)  {
        System.out.printf("\n\n\nbody: %s\n\n\n\n", body);
        return "Hello WebFlux";
    }
}

If you make correct request you will see correct response:

$ curl -i -w "\n\n" -XPOST -d "asd" -H "Content-Type: application/json" http://localhost:8080/hello
HTTP/1.1 200 OK
Content-Type: text/plain;charset=UTF-8
Content-Length: 13

Hello WebFlux

If you make a mistake you will receive 500 and lot's of logs that don't tell you what has happened:

curl -i -w "\n\n" -XPOST -d "asd" http://localhost:8080/hello
HTTP/1.1 500 Internal Server Error
Content-Type: application/json;charset=UTF-8
Content-Length: 16111

{"timestamp":"2019-02-27T16:12:13.095+0000","path":"/hello","status":500,"error":"Internal Server Error","message":"Only one connection receive subscriber allowed.","trace":"java.lang.IllegalStateException: Only one connection receive subscriber allowed.\n\tat reactor.netty.channel.FluxReceive.startReceiver(FluxReceive.java:271)\n\tat reactor.netty.channel.FluxReceive.subscribe(FluxReceive.java:121)\n\tat reactor.core.publisher.FluxMap.subscribe(FluxMap.java:62)\n\tat reactor.core.publisher.FluxOnAssembly.subscribe(FluxOnAssembly.java:132)\n\tat reactor.netty.ByteBufFlux.subscribe(ByteBufFlux.java:294)\n\tat 

...

You can see the same exception in application logs:

2019-02-27 17:12:13.109 ERROR 32312 --- [or-http-epoll-3] a.w.r.e.AbstractErrorWebExceptionHandler : [8aba656e] 500 Server Error for HTTP POST "/hello"

java.lang.IllegalStateException: Only one connection receive subscriber allowed.
        at reactor.netty.channel.FluxReceive.startReceiver(FluxReceive.java:271) ~[reactor-netty-0.8.5.RELEASE.jar:0.8.5.RELEASE]
        at reactor.netty.channel.FluxReceive.subscribe(FluxReceive.java:121) ~[reactor-netty-0.8.5.RELEASE.jar:0.8.5.RELEASE]
        at reactor.core.publisher.FluxMap.subscribe(FluxMap.java:62) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxOnAssembly.subscribe(FluxOnAssembly.java:132) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.netty.ByteBufFlux.subscribe(ByteBufFlux.java:294) ~[reactor-netty-0.8.5.RELEASE.jar:0.8.5.RELEASE]
        at reactor.core.publisher.FluxPeek.subscribe(FluxPeek.java:83) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxOnAssembly.subscribe(FluxOnAssembly.java:132) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.netty.ByteBufFlux.subscribe(ByteBufFlux.java:294) ~[reactor-netty-0.8.5.RELEASE.jar:0.8.5.RELEASE]
        at reactor.core.publisher.FluxMap.subscribe(FluxMap.java:62) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxOnAssembly.subscribe(FluxOnAssembly.java:132) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoCollectList.subscribe(MonoCollectList.java:59) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:56) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoFilterFuseable.subscribe(MonoFilterFuseable.java:44) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:56) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoMapFuseable.subscribe(MonoMapFuseable.java:56) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:56) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoSubscriberContext.subscribe(MonoSubscriberContext.java:47) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoMapFuseable.subscribe(MonoMapFuseable.java:59) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoOnErrorResume.subscribe(MonoOnErrorResume.java:44) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoSwitchIfEmpty.subscribe(MonoSwitchIfEmpty.java:44) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoDefaultIfEmpty.subscribe(MonoDefaultIfEmpty.java:37) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoPeekFuseable.subscribe(MonoPeekFuseable.java:74) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.Mono.subscribe(Mono.java:3694) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoZip.subscribe(MonoZip.java:128) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoFlatMap.subscribe(MonoFlatMap.java:60) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:153) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoPeekFuseable.subscribe(MonoPeekFuseable.java:74) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoPeekFuseable.subscribe(MonoPeekFuseable.java:74) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoOnErrorResume.subscribe(MonoOnErrorResume.java:44) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:150) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:353) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:67) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:353) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:76) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:353) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.innerNext(FluxConcatMap.java:275) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxConcatMap$ConcatMapInner.onNext(FluxConcatMap.java:849) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:353) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:114) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:353) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2070) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.request(FluxOnAssembly.java:438) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxMap$MapSubscriber.request(FluxMap.java:155) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.request(FluxOnAssembly.java:438) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.set(Operators.java:1878) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onSubscribe(Operators.java:1752) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onSubscribe(FluxOnAssembly.java:422) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxMap$MapSubscriber.onSubscribe(FluxMap.java:86) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onSubscribe(FluxOnAssembly.java:422) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:54) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoCallableOnAssembly.subscribe(MonoCallableOnAssembly.java:82) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoMap.subscribe(MonoMap.java:55) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.Mono.subscribe(Mono.java:3694) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.drain(FluxConcatMap.java:442) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.onSubscribe(FluxConcatMap.java:212) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onSubscribe(FluxOnAssembly.java:422) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:139) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:63) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxOnAssembly.subscribe(FluxOnAssembly.java:132) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxConcatMap.subscribe(FluxConcatMap.java:121) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxOnAssembly.subscribe(FluxOnAssembly.java:132) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoNext.subscribe(MonoNext.java:40) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoSwitchIfEmpty.subscribe(MonoSwitchIfEmpty.java:44) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoFlatMap.subscribe(MonoFlatMap.java:60) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoFlatMap.subscribe(MonoFlatMap.java:60) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:150) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:353) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:121) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:353) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1505) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoProcessor.onNext(MonoProcessor.java:389) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:353) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:67) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:353) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:121) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxContextStart$ContextStartSubscriber.onNext(FluxContextStart.java:103) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:353) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxMapFuseable$MapFuseableConditionalSubscriber.onNext(FluxMapFuseable.java:287) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:353) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxFilterFuseable$FilterFuseableConditionalSubscriber.onNext(FluxFilterFuseable.java:331) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:353) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1505) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.MonoCollectList$MonoBufferAllSubscriber.onComplete(MonoCollectList.java:118) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onComplete(FluxOnAssembly.java:363) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:136) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onComplete(FluxOnAssembly.java:363) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:252) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onComplete(FluxOnAssembly.java:363) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:136) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
        at reactor.netty.channel.FluxReceive.terminateReceiver(FluxReceive.java:372) ~[reactor-netty-0.8.5.RELEASE.jar:0.8.5.RELEASE]
        at reactor.netty.channel.FluxReceive.drainReceiver(FluxReceive.java:196) ~[reactor-netty-0.8.5.RELEASE.jar:0.8.5.RELEASE]
        at reactor.netty.channel.FluxReceive.onInboundComplete(FluxReceive.java:337) ~[reactor-netty-0.8.5.RELEASE.jar:0.8.5.RELEASE]
        at reactor.netty.channel.ChannelOperations.onInboundComplete(ChannelOperations.java:334) ~[reactor-netty-0.8.5.RELEASE.jar:0.8.5.RELEASE]
        at reactor.netty.http.server.HttpServerOperations.onInboundNext(HttpServerOperations.java:453) ~[reactor-netty-0.8.5.RELEASE.jar:0.8.5.RELEASE]
        at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:141) ~[reactor-netty-0.8.5.RELEASE.jar:0.8.5.RELEASE]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
        at reactor.netty.http.server.HttpTrafficHandler.channelRead(HttpTrafficHandler.java:191) ~[reactor-netty-0.8.5.RELEASE.jar:0.8.5.RELEASE]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
        at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:438) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:323) ~[netty-codec-4.1.33.Final.jar:4.1.33.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:297) ~[netty-codec-4.1.33.Final.jar:4.1.33.Final]
        at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:253) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
        at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1408) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
        at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:930) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
        at io.netty.channel.epoll.AbstractEpollStreamChannel$EpollStreamUnsafe.epollInReady(AbstractEpollStreamChannel.java:799) ~[netty-transport-native-epoll-4.1.33.Final-linux-x86_64.jar:4.1.33.Final]
        at io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:427) ~[netty-transport-native-epoll-4.1.33.Final-linux-x86_64.jar:4.1.33.Final]
        at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:328) ~[netty-transport-native-epoll-4.1.33.Final-linux-x86_64.jar:4.1.33.Final]
        at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:905) ~[netty-common-4.1.33.Final.jar:4.1.33.Final]
        at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_201]
        Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Assembly trace from producer [reactor.core.publisher.FluxMap] :
        reactor.core.publisher.Flux.map(Flux.java:5689)
        reactor.netty.ByteBufFlux.fromInbound(ByteBufFlux.java:70)
Error has been observed by the following operator(s):
        |_      Flux.map ⇢ reactor.netty.ByteBufFlux.fromInbound(ByteBufFlux.java:70)
        |_      Flux.doOnNext ⇢ reactor.netty.ByteBufFlux.retain(ByteBufFlux.java:282)
        |_      Flux.map ⇢ org.springframework.http.server.reactive.ReactorServerHttpRequest.getBody(ReactorServerHttpRequest.java:166)
        |_      Flux.collectList ⇢ org.springframework.core.io.buffer.DataBufferUtils.join(DataBufferUtils.java:438)
        |_      Mono.filter ⇢ org.springframework.core.io.buffer.DataBufferUtils.join(DataBufferUtils.java:439)
        |_      Mono.map ⇢ org.springframework.core.io.buffer.DataBufferUtils.join(DataBufferUtils.java:440)
        |_      Mono.map ⇢ org.springframework.core.codec.AbstractDataBufferDecoder.decodeToMono(AbstractDataBufferDecoder.java:68)
        |_      Mono.error ⇢ org.springframework.web.reactive.result.method.annotation.AbstractMessageReaderArgumentResolver.lambda$readBody$4(AbstractMessageReaderArgumentResolver.java:186)
        |_      Mono.onErrorResume ⇢ org.springframework.web.reactive.result.method.annotation.AbstractMessageReaderArgumentResolver.readBody(AbstractMessageReaderArgumentResolver.java:186)
        |_      Mono.switchIfEmpty ⇢ org.springframework.web.reactive.result.method.annotation.AbstractMessageReaderArgumentResolver.readBody(AbstractMessageReaderArgumentResolver.java:188)
        |_      Mono.defaultIfEmpty ⇢ org.springframework.web.reactive.result.method.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:192)
        |_      Mono.doOnError ⇢ org.springframework.web.reactive.result.method.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:193)
        |_      Mono.zip ⇢ org.springframework.web.reactive.result.method.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:200)
        |_      Mono.flatMap ⇢ org.springframework.web.reactive.result.method.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:135)
        |_      Mono.defer ⇢ org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter.handle(RequestMappingHandlerAdapter.java:199)
        |_      Mono.then ⇢ org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter.handle(RequestMappingHandlerAdapter.java:199)
        |_      Mono.doOnNext ⇢ org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter.handle(RequestMappingHandlerAdapter.java:200)
        |_      Mono.doOnNext ⇢ org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter.handle(RequestMappingHandlerAdapter.java:201)
        |_      Mono.error ⇢ org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter.handleException(RequestMappingHandlerAdapter.java:234)
        |_      Mono.onErrorResume ⇢ org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter.handle(RequestMappingHandlerAdapter.java:202)
        |_      Mono.flatMap ⇢ org.springframework.web.reactive.DispatcherHandler.handle(DispatcherHandler.java:151)
        |_      Mono.flatMap ⇢ org.springframework.web.reactive.DispatcherHandler.handle(DispatcherHandler.java:152)
        |_      Mono.defer ⇢ org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:119)
        |_      Mono.flatMap ⇢ org.springframework.web.filter.reactive.HiddenHttpMethodFilter.filter(HiddenHttpMethodFilter.java:90)
        |_      Mono.defer ⇢ org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:119)


This exception is masking real problem and causing a lot of confusion. I noticed that there is a lot issues that mention this exception, so this seems like a widespread problem: https://github.com/spring-projects/spring-framework/issues?q=is%3Aissue+Only+one+connection+receive

Would it be possible to present real exception in logs to make debugging easier?

Thanks!

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Feb 27, 2019
@bclozel
Copy link
Member

bclozel commented Mar 4, 2019

This exception happens when your application is trying to read twice the request body, and this is forbidden as this would work against backpressure support. Many things can lead to this particular symptom, so this is why you're seeing this error multiple times in our tracker. This doesn't mean the same problem is widespread.

In your case, your curl request is sending the request body with Content-Type: application/x-www-form-urlencoded; Spring Boot has an auto-configured WebFilter that parses the form request and makes it available for binding. Then the request is mapped to a controller handler that asks for the full request body with @RequestBody. This is where the problem comes from.

I'll leave this issue opened for now, in case we can get a clearer message for this particular case.

@sbrannen sbrannen added the in: web Issues in web modules (web, webmvc, webflux, websocket) label Mar 5, 2019
@rstoyanchev
Copy link
Contributor

I think we could get a better message.

This is happening in AbstractMessageReaderArgumentResolver, so one option would be to anticipate the issue for @RequestBody arguments , in handleReadError we could check if the content-type is application/x-www-form-urlencoded and if the error message contains "only one connection", and if so extend the error message to also say "This could be because ...".

Alternatively, we could make the same check from HiddenHttpMethodFilter itself on the way out and enhance the error message.

@rstoyanchev rstoyanchev removed the status: waiting-for-triage An issue we've not yet triaged or decided on label Mar 6, 2019
@rstoyanchev rstoyanchev added this to the 5.2 M1 milestone Mar 6, 2019
@rstoyanchev rstoyanchev self-assigned this Mar 20, 2019
@rstoyanchev rstoyanchev added the type: enhancement A general enhancement label Mar 20, 2019
@rstoyanchev rstoyanchev changed the title "java.lang.IllegalStateException: Only one connection receive subscriber allowed." is masking real exceptions in WebFlux. @RequestBody raises IllegalStateException for form data Apr 10, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

5 participants