An IllegalArgumentException is thrown when an expected error occurs during the execution of a StreamingResponseBody. For example:

@GetMapping("/read")
public ResponseEntity<StreamingResponseBody> read(@RequestHeader Map<String, String> headers) {
    return new ResponseEntity<>(outputStream -> {
        throw new IOException("error");
    }, HttpStatus.OK);
}

Produces the following log entry:

2020-04-01 06:37:33.897  WARN 71407 --- [nio-8080-exec-2] o.apache.catalina.core.AsyncContextImpl  : onError() call failed for listener of type [org.apache.catalina.core.AsyncListenerWrapper]

java.lang.IllegalArgumentException: Cannot dispatch without an AsyncContext
    at org.springframework.util.Assert.notNull(Assert.java:198) ~[spring-core-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.springframework.web.context.request.async.StandardServletAsyncWebRequest.dispatch(StandardServletAsyncWebRequest.java:131) ~[spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.springframework.web.context.request.async.WebAsyncManager.setConcurrentResultAndDispatch(WebAsyncManager.java:391) ~[spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.springframework.web.context.request.async.WebAsyncManager.lambda$startCallableProcessing$2(WebAsyncManager.java:315) ~[spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.springframework.web.context.request.async.StandardServletAsyncWebRequest.lambda$onError$0(StandardServletAsyncWebRequest.java:146) ~[spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1540) ~[na:na]
    at org.springframework.web.context.request.async.StandardServletAsyncWebRequest.onError(StandardServletAsyncWebRequest.java:146) ~[spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.apache.catalina.core.AsyncListenerWrapper.fireOnError(AsyncListenerWrapper.java:49) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.AsyncContextImpl.setErrorState(AsyncContextImpl.java:422) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.connector.CoyoteAdapter.asyncDispatch(CoyoteAdapter.java:239) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.coyote.AbstractProcessor.dispatch(AbstractProcessor.java:237) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:59) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1594) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]

The expected IOException is handled well during the execution, and on the client side, a well formed JSON with the expected error payload is received. However, the error is adding noise to the log entry.

Comment From: rstoyanchev

After the exception is raised, we do an async dispatch to have it resolved but as it remains unresolved, and in the error dispatch, Boot prepares and error response. At this point, after the error dispatch, Tomcat and Undertow notify AsyncListener#onError. I'm not sure if that's per spec behavior, my reading is that it is, but Jetty doesn't do that.

In any case I've added a fix to skip over onError handling if we know that concurrent handling produced an error.

Comment From: alohahahaha

hi, Have you solved this problem?