Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"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

Closed
mgocd opened this issue Feb 6, 2024 · 0 comments
Assignees
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

Comments

@mgocd
Copy link

mgocd commented Feb 6, 2024

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 an IllegalStateException with message Cannot 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 runs response.sendError(400), making the httpServletResponse.isCommitted() return true starting from this point.

When Spring's DefaultHandlerExceptionResolver#handleHttpMessageNotReadable:587 runs response.sendError(400) again, it throws the IllegalStateException: Cannot call sendError() after the response has been committed.

To resolve the issue, DefaultHandlerExceptionResolver#handleHttpMessageNotReadable could run response.sendError conditionally, only if !response.isCommitted(), similarly as done in DefaultHandlerExceptionResolver#handleErrorResponse:514.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Feb 6, 2024
@jhoeller jhoeller added in: web Issues in web modules (web, webmvc, webflux, websocket) type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Feb 6, 2024
@jhoeller jhoeller self-assigned this Feb 6, 2024
@jhoeller jhoeller added this to the 6.1.4 milestone Feb 6, 2024
@github-actions github-actions bot added status: backported An issue that has been backported to maintenance branches and removed for: backport-to-6.0.x labels Feb 6, 2024
jhoeller added a commit that referenced this issue Feb 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
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
Projects
None yet
Development

No branches or pull requests

3 participants