The class "AsyncTimeoutRedirectFilter" swallows almost all the exceptions

Steps to reproduce

Steps to reproduce:
This bug is relatively hard to reproduce. It prevented me from identifying the bug for a very long time, because the exception created was silently discarded by this filter.

The filter is a fix for MH-10829. Its purpose seems to be to catch two specific types of exceptions and return an unauthorized exception to force a redirection to the login site. However, the code fails to return any exception that does not belong to these two types, and therefore a default "200 OK" response is returned instead of an error.

The relevant code is this:

} catch (Exception ex) {
Throwable[] causeChain = throwableAnalyzer.determineCauseChain(ex);
RuntimeException exception = (AuthenticationException) throwableAnalyzer.getFirstThrowableOfType(
AuthenticationException.class, causeChain);

if (exception == null) {
exception = (AccessDeniedException) throwableAnalyzer.getFirstThrowableOfType(AccessDeniedException.class,

if (exception != null) {
if (exception instanceof AuthenticationException) {
throw exception;
} else if (exception instanceof AccessDeniedException) {

if (authenticationTrustResolver.isAnonymous(SecurityContextHolder.getContext().getAuthentication())) {
logger.debug("User session expired or not logged in yet");

String ajaxHeader = ((HttpServletRequest) request).getHeader("X-Requested-With");

// If asynchronous request, we returned the error code set, otherwise we redirect to the login page
if ("XMLHttpRequest".equals(ajaxHeader)) {
logger.debug("Asynchronous call detected, send {} error code", TIMEOUT_ERROR_CODE);
HttpServletResponse resp = (HttpServletResponse) response;
} else {
logger.debug("Redirect to login page");
throw exception;
} else {
throw exception;


Fixed and reviewed
Your pinned fields
Click on the next to a field label to start pinning.


Rubén Pérez


Rubén Pérez


Incorrectly Functioning Without Workaround