Skip to content

Double error response handling on suspended methods #31541

@nilskohrs

Description

@nilskohrs

The combination of spring-boot-starter-web, kotlinx-coroutines-reactor, a suspended controller method and handling a 500 error response through ResponseEntityExceptionHandler causes double exception handling and response bodies.

The first response body is generated by the ProblemDetail handled with ResponseEntityExceptionHandler.handleException(...), the second is generated by BasicErrorController

Reproduction steps (tested on version 3.0.0 and 3.1.2):

  • Create spring initializr project with Kotlin and spring-boot-starter-web
  • Add org.jetbrains.kotlinx:kotlinx-coroutines-reactor dependency
  • Run following code
@SpringBootApplication class DemoApplication fun main(args: Array<String>) { runApplication<DemoApplication>(*args) } @RestController class Controller { @GetMapping("normal") fun normalScenario() { throw IllegalStateException("Returns problemdetail") } @GetMapping("suspend") suspend fun errorScenario() { throw IllegalStateException("Double exception handling") } } @ControllerAdvice class ExceptionHandler : ResponseEntityExceptionHandler() { @ExceptionHandler(Exception::class) fun handleUnexpectedTechnicalException( ex: Exception, request: WebRequest ): ResponseEntity<Any>? { return handleException( ErrorResponseException( HttpStatus.INTERNAL_SERVER_ERROR, ProblemDetail.forStatus(500), ex ), request ) } }

Endpoint /normal returns the expected Problem Detail

Endpoint /suspend with postman returns double body response (body size + ProblemDetail and then body size + BasicErrorController's response). Since this response is an invalid http response, a proxy like fiddler is needed to see this double response being returned.

HTTP/1.1 500 Content-Type: application/problem+json Transfer-Encoding: chunked Date: Tue, 08 Aug 2023 09:26:30 GMT Connection: close 59 {"type":"about:blank","title":"Internal Server Error","status":500,"instance":"/suspend"} 6c {"timestamp":"2023-08-08T09:26:30.705+00:00","status":500,"error":"Internal Server Error","path":"/suspend"} 

Endpoint /suspend with chrome triggers following error:
s.e.ErrorMvcAutoConfiguration$StaticView : Cannot render error page for request [/suspend] as the response has already been committed. As a result, the response may have the wrong status code.

Metadata

Metadata

Assignees

Labels

in: webIssues in web modules (web, webmvc, webflux, websocket)status: backportedAn issue that has been backported to maintenance branchestype: bugA general bug

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions