"IllegalStateException: Cannot call sendError() after the response has been committed" when IOException is thrown during resolving method argument values on Tomcat >= 10.1.16 #32206
Labels
in: web
Issues in web modules (web, webmvc, webflux, websocket)
status: backported
An issue that has been backported to maintenance branches
type: bug
A general bug
Milestone
Affects: Spring Framework 6.1.3 with Tomcat >= 10.1.16 (or Spring Boot >= 3.1.6, including 3.2.x)
Description
When an
IOException
is thrown during resolving method argument values for a Rest Controller (in Tomcat's InputBuffer#realReadBytes#313, invoked by Spring's AbstractMessageConverterMethodArgumentResolver#readWithMessageConverters#174), Spring's DefaultHandlerExceptionResolver#handleHttpMessageNotReadable:587 throws anIllegalStateException
with messageCannot call sendError() after the response has been committed
.This also results in setting HTTP response status code to 500 instead of 400.
In Spring Framework 6.1.3 with Tomcat 10.1.15 the
IllegalStateException
is not thrown, and the HTTP status code is 400.Reproduction
See https://github.com/mgocd/spring-httpmessagenotreadableexception-resolve-issue
Analysis
Starting from Tomcat 10.1.16 (because of this commit) the exception handler inside
InputBuffer#realReadBytes
runsresponse.sendError(400)
, making thehttpServletResponse.isCommitted()
returntrue
starting from this point.When Spring's DefaultHandlerExceptionResolver#handleHttpMessageNotReadable:587 runs
response.sendError(400)
again, it throws theIllegalStateException: Cannot call sendError() after the response has been committed
.To resolve the issue,
DefaultHandlerExceptionResolver#handleHttpMessageNotReadable
could runresponse.sendError
conditionally, only if!response.isCommitted()
, similarly as done in DefaultHandlerExceptionResolver#handleErrorResponse:514.The text was updated successfully, but these errors were encountered: