Hi, I had custom my own exception controller like this

@ControllerAdvice
public class DefaultExceptionHandler {

    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultExceptionHandler.class); 

    @ExceptionHandler(RuntimeException.class)
    @ResponseBody
    public ResponseData exceptionHandler(Exception exception,
            HttpServletRequest request,
            HttpServletResponse response) {


        ResponseData data = new ResponseData();
        data.setCode(-1);
        data.setSuccess(false);

        if (exception instanceof CustomizeRuntimeException) {
            var customException = (CustomizeRuntimeException)exception;
            data.setMessage(customException.getMessage());
        }
        else if (exception instanceof HttpRequestMethodNotSupportedException) {
            data.setMessage(exception.getMessage());
        }
        else {
            data.setMessage(exception.getMessage());
            exception.printStackTrace();
        }

        return data;
    }
}

and when there is a json serialize exception, I found I get two body from response.

{
    "message": "get session list successfully",
    "success": true,
    "code": 0,
    "result": {
        "id": "FCC0BF0A376C7BE89FAE26CEC9B6B77E",
        "creationTime": 1609640049356,
    }
}{
    "message": "Type definition error: [simple type, class java.util.logging.ErrorManager]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class java.util.logging.ErrorManager and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: com.mozzie.background.model.ResponseData[\"result\"]->org.apache.catalina.session.StandardSessionFacade[\"servletContext\"]->org.apache.catalina.core.ApplicationContextFacade[\"classLoader\"]->org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader[\"resources\"]->org.apache.catalina.webresources.StandardRoot[\"context\"]->org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedContext[\"logger\"]->org.apache.juli.logging.DirectJDKLog[\"logger\"]->java.util.logging.Logger[\"parent\"]->java.util.logging.Logger[\"parent\"]->java.util.logging.Logger[\"parent\"]->java.util.logging.Logger[\"parent\"]->java.util.logging.LogManager$RootLogger[\"handlers\"]->org.slf4j.bridge.SLF4JBridgeHandler[0]->org.slf4j.bridge.SLF4JBridgeHandler[\"errorManager\"])",
    "success": false,
    "code": -1,
    "result": null
}

Why is this so? and how to make it only response once before I solve the serialize exception?

Comment From: wilkinsona

Why is this so?

I can't say for certain without some more information, but I would guess that you have written and flushed some output to the response stream before the error handling has kicked in.

If you would like us to spend some more time investigating, please spend some time providing a complete yet minimal sample that reproduces the problem. You can share it with us by pushing it to a separate repository on GitHub or by zipping it up and attaching it to this issue.

Comment From: bclozel

@darkgirl this comment might give you some insight.

  1. If your exception handler was previously working and you're on Spring Boot 2.3.x, upgrading to 2.3.7.RELEASE will revert a behavior change and this might fix the problem
  2. If this is a new exception handler and you're seeing this problem now, this just means that you're catching an exception that happens while writing the response body and some content has been flushed to response itself

I think an exception handler catching RuntimeException is too generic and there is no way to guarantee that you won't encouter such problems.

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: darkgirl

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.

sorry for taking so long to reply. I uploaded a mini project, hope it would helpful, thanks response_test.zip

Comment From: wilkinsona

Thanks for the sample. An error is occurring while trying to serialise the response from your CustomizeErrorController. You need to ensure that your error controller does not itself create any errors. This is one reason why Boot's BasicErrorController returns a Map which reduces the risk of a JSON serialisation failure occurring.

Comment From: darkgirl

Thanks for the sample. An error is occurring while trying to serialise the response from your CustomizeErrorController. You need to ensure that your error controller does not itself create any errors. This is one reason why Boot's BasicErrorController returns a Map which reduces the risk of a JSON serialisation failure occurring.

You need to ensure that your error controller does not itself create any errors. you mean there is some errors in my error controller? but if you move hello = new Object to TestJsonExceptionController, my error controller will not have any error but the problem still. response_test.zip

Comment From: wilkinsona

you mean there is some errors in my error controller?

Yes. Your error controller is returning a POJO that cannot be serialised the JSON. This serialisation failure results in an error.

but if you move hello = new Object to TestJsonExceptionController, my error controller will not have any error but the problem still

This is the situation that @bclozel described above:

If this is a new exception handler and you're seeing this problem now, this just means that you're catching an exception that happens while writing the response body and some content has been flushed to response itself I think an exception handler catching RuntimeException is too generic and there is no way to guarantee that you won't encounter such problems.

Your exception handler is broader than this as it handles Exception. When it handles an HttpMessageConversionException some of the response may already have been written and your handler is then writing additional content to the response body. You should avoid doing so unless you are certain that the writing of the response has not already begun, typically by narrowing your exception handler to only deal with specific exceptions.

If you have any further questions, please follow up on Stack Overflow or Gitter. As mentioned in the guidelines for contributing, we prefer to use GitHub issues only for bugs and enhancements.