406 when exception thrown in Spring controller with accept header of text/csv
==== Original Answer (explaining the expected behavior) ====
The Accept
header specifies the format type which client expects the server to respond with. Any variance to this leads to HTTP 406 - Not Acceptable
error. This error however does not means that the operation failed, however it indicates that the client expectation failed for the specified format.
In your case the Accept
header carries text/csv
but server responds with application/json
, thus the 406
error because there is a clear mismatch.
To correct this behavior there is no change required on server / spring end. Instead the client should start sending Accept
header which will carry value as application/json,text/csv
. This will ensure that client expects both formats and supports them in case of valid / error response.
Refer here for more details.
Edit 22nd Dec, 2017
The observed behavior is confirmed as a bug by Spring team here. No known workaround available yet.
Edit 04th Jan, 2018
As mentioned in Spring JIRA comments as a workaround we need to remove the HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE
request attribute in @RestControllerAdvice
. The code could look something like below (returns a 500 with some "info" -- a serialized version of the object is also returned).
Rest controller Advice
@RestControllerAdvice
public class ExampleControllerAdvice {
@ExceptionHandler(value = Exception.class)
public ResponseEntity<ErrorResponse> handleException(HttpServletRequest request, Exception e) {
ErrorResponse response = new ErrorResponse();
response.setErrorMsg("Server error " + e); // or whatever you want
response.setErrorCode("ERROR007"); // or whatever you want
request.removeAttribute(
HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
return new ResponseEntity<ErrorResponse>(response, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
ErrorResponse object
public class ErrorResponse {
private String errorCode;
private String errorMsg;
public String getErrorCode() {
return errorCode;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
public String getErrorMsg() {
return errorMsg;
}
public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}
}
Edit 27th Jun, 2019
This is fixed now in Spring Framework. The request attribute HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE
now removed automatically by Spring before handling an exception.