Skip to content

Failure in @ExceptionHandler from IOException: The response may not be written to once it has been closed #36421

@msqr

Description

@msqr

In Spring 7 Webmvc, I am getting exceptions propagated to the Servlet container after an @ExceptionHandler tries to render a result but the connection is closed. I was hoping the DisconnectedClientHelper would identify and silence this scenario, i.e. return true from isClientDisconnectedException(ex).

An example exception is:

[2026-03-05 16:44:49.245] WARN  [http-nio-9082-exec-7570 ] .m.m.a.ExceptionHandlerExceptionResolver Failure in @ExceptionHandler net.solarnetwork.central.web.support.WebServiceGlobalControllerSupport#handleTransientDataAccessException(TransientDataAccessException, WebRequest, Locale)
org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: The response may not be written to once it has been closed
org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: The response may not be written to once it has been closed
	at org.springframework.http.converter.AbstractJacksonHttpMessageConverter.writeInternal(AbstractJacksonHttpMessageConverter.java:443)
	at org.springframework.http.converter.AbstractJacksonHttpMessageConverter.writeInternal(AbstractJacksonHttpMessageConverter.java:443)
	at org.springframework.http.converter.AbstractSmartHttpMessageConverter.write(AbstractSmartHttpMessageConverter.java:117)
	at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:343)
	at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:207)
	at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:78)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:135)
	at org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver.doResolveHandlerMethodException(ExceptionHandlerExceptionResolver.java:460)
	at org.springframework.web.servlet.handler.AbstractHandlerMethodExceptionResolver.doResolveException(AbstractHandlerMethodExceptionResolver.java:72)
	at org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.resolveException(AbstractHandlerExceptionResolver.java:176)
	at org.springframework.web.servlet.handler.HandlerExceptionResolverComposite.resolveException(HandlerExceptionResolverComposite.java:78)
	at org.springframework.web.servlet.DispatcherServlet.processHandlerException(DispatcherServlet.java:1227)
	at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1035)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:980)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:866)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1003)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:892)
...
Caused by: tools.jackson.core.exc.JacksonIOException: The response may not be written to once it has been closed
 at [No location information]
	at tools.jackson.core.exc.JacksonIOException.construct(JacksonIOException.java:39)
	at tools.jackson.core.JsonGenerator._wrapIOFailure(JsonGenerator.java:2476)
	at tools.jackson.core.json.UTF8JsonGenerator._flushBuffer(UTF8JsonGenerator.java:2343)
	at tools.jackson.core.json.UTF8JsonGenerator.flush(UTF8JsonGenerator.java:1235)
	at tools.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:975)
	at org.springframework.http.converter.AbstractJacksonHttpMessageConverter.writeInternal(AbstractJacksonHttpMessageConverter.java:435)
	... 134 common frames omitted
Caused by: java.io.IOException: The response may not be written to once it has been closed
	at org.apache.catalina.connector.OutputBuffer.writeBytes(OutputBuffer.java:360)
	at org.apache.catalina.connector.OutputBuffer.write(OutputBuffer.java:341)
	at org.apache.catalina.connector.CoyoteOutputStream.write(CoyoteOutputStream.java:99)
	at org.springframework.security.web.util.OnCommittedResponseWrapper$SaveContextServletOutputStream.write(OnCommittedResponseWrapper.java:639)
	at org.springframework.util.StreamUtils$NonClosingOutputStream.write(StreamUtils.java:284)
	at tools.jackson.core.json.UTF8JsonGenerator._flushBuffer(UTF8JsonGenerator.java:2341)
	... 137 common frames omitted

Or is there a way to configure such exceptions to not propagate to the Servlet container?

Metadata

Metadata

Assignees

No one assigned

    Labels

    in: webIssues in web modules (web, webmvc, webflux, websocket)status: waiting-for-triageAn issue we've not yet triaged or decided on

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions