- Notifications
You must be signed in to change notification settings - Fork 38.9k
Description
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.