Affects: Spring boot 3.2.4


Since upgrading to Spring boot 3.2.4 from 3.2.3 the Custom exception handler does not send response with the custom message in body.

Spring boot 3.2.3

MockHttpServletResponse:
           Status = 500
    Error message = null
          Headers = [Content-Type:"application/json"]
     Content type = application/json
             Body = {"status":"INTERNAL_SERVER_ERROR","message":"An error occurred."}
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

Spring boot 3.2.4+

MockHttpServletResponse:
           Status = 500
    Error message = null
          Headers = [Content-Type:"application/json"]
     Content type = application/json
             Body = 
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

I have reproduced the issue in this sample project, DeferredDemo.zip. This issue persists in Spring Boot 3.3.0

Comment From: Meijuh

Related to the problem here, might be the work done in this issue: https://github.com/spring-projects/spring-framework/issues/32340.

Comment From: rstoyanchev

The sample doesn't seem to be working as described above. DemoController returns new DeferredResult(). That results in AsyncRequestTimeoutException, which is handled by DemoExceptionHandler but it uses the exception message which is null. I changed it to ""An error occurred." but it works with both 3.2.4 and 3.2.3.

Comment From: bthers-dish

It is curious that it is working for you but fails on our systems. I have tested it with both Java 17 and 21.

I added AsyncRequestTimeoutException exception handling to the DemoExceptionHandler and added a test to throw the AsyncRequestTimeoutException. I also set the message of the error response to the exception title.

Spring Custom Exception body empty

Both tests are still failing with an Unparsable JSON string message due to the response body being empty. DeferredDemo.zip

Comment From: rstoyanchev

The tests are using AsyncListener#onError which typically indicates a network or I/O error after the response is no longer usable. We now protect the response from being used in such cases because Servlet containers recycle the request and response and writing may affect the response for a different request.

If I switch the timeout test on AsyncListener#onTimeout which is what is actually called in case of a timeout, the test passes.

Comment From: spring-projects-issues

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

Comment From: spring-projects-issues

Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.