spring-projects/spring-security · warning
AuthenticationException must be of type %s but was %s
Error message
AuthenticationException must be of type %s but was %s
What it means
OAuth2ErrorAuthenticationFailureHandler.onAuthenticationFailure() can only render OAuth2 errors; if the thrown AuthenticationException is not an OAuth2AuthenticationException it cannot convert it to an error response, so it only logs a warning naming the actual exception type and returns without writing a response.
Source
Thrown at oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2ErrorAuthenticationFailureHandler.java:65
public final class OAuth2ErrorAuthenticationFailureHandler implements AuthenticationFailureHandler {
private final Log logger = LogFactory.getLog(getClass());
private HttpMessageConverter<OAuth2Error> errorResponseConverter = new OAuth2ErrorHttpMessageConverter();
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authenticationException) throws IOException, ServletException {
ServletServerHttpResponse httpResponse = new ServletServerHttpResponse(response);
httpResponse.setStatusCode(HttpStatus.BAD_REQUEST);
if (authenticationException instanceof OAuth2AuthenticationException oauth2AuthenticationException) {
OAuth2Error error = oauth2AuthenticationException.getError();
this.errorResponseConverter.write(error, null, httpResponse);
}
else {
if (this.logger.isWarnEnabled()) {
this.logger.warn(AuthenticationException.class.getSimpleName() + " must be of type "
+ OAuth2AuthenticationException.class.getName() + " but was "
+ authenticationException.getClass().getName());
}
}
}
/**
* Sets the {@link HttpMessageConverter} used for converting an {@link OAuth2Error} to
* an HTTP response.
* @param errorResponseConverter the {@link HttpMessageConverter} used for converting
* an {@link OAuth2Error} to an HTTP response
*/
public void setErrorResponseConverter(HttpMessageConverter<OAuth2Error> errorResponseConverter) {
Assert.notNull(errorResponseConverter, "errorResponseConverter cannot be null");
this.errorResponseConverter = errorResponseConverter;
}
}View on GitHub (pinned to 96852e8860)
Solutions
- Find which provider/filter throws the non-OAuth2 exception and make it throw OAuth2AuthenticationException with a proper OAuth2Error
- Register this handler only on filters that exclusively produce OAuth2AuthenticationException (e.g. OAuth2 authorization endpoint, token endpoint)
- Add a fallback AuthenticationFailureHandler that handles generic AuthenticationExceptions
Example fix
// before
throw new BadCredentialsException("invalid token");
// after
throw new OAuth2AuthenticationException(new OAuth2Error("invalid_token", "invalid token", null)); Defensive patterns
Strategy: type-guard
Validate before calling
if (!(ex instanceof OAuth2AuthenticationException)) {
logger.warn("Non-OAuth2 AuthenticationException routed to OAuth2ErrorAuthenticationFailureHandler: " + ex.getClass().getName());
} Type guard
if (authenticationException instanceof OAuth2AuthenticationException oauth2Ex) {
// safe: handler can render oauth2Ex.getError()
} Try / catch
try {
filterChain.doFilter(request, response);
} catch (AuthenticationException ex) {
OAuth2Error error = (ex instanceof OAuth2AuthenticationException o) ? o.getError()
: new OAuth2Error("server_error", ex.getMessage(), null);
// write error via converter
} Prevention
- Only attach OAuth2ErrorAuthenticationFailureHandler to endpoints that throw OAuth2AuthenticationException
- Have custom AuthenticationProviders throw OAuth2AuthenticationException with an OAuth2Error
- Chain a generic AuthenticationFailureHandler as fallback for other exception types
When it happens
Trigger: Registering an OAuth2ErrorAuthenticationFailureHandler on an authentication filter/endpoint where a non-OAuth2 AuthenticationException (e.g. BadCredentialsException, UsernameNotFoundException, DisabledException) can be thrown.
Common situations: Wiring the OAuth2 failure handler into the standard form-login or bearer-token failure path by mistake; custom providers throwing plain BadCredentialsException inside an OAuth2 flow.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- oidc_provider_not_configured
- OAuth2Error from upstream authorization exception (dynamic)
- RunAsImplAuthenticationProvider.incorrectKey
- Authenticated principal required to operate with ACLs
- CasAuthenticationProvider.incorrectKey
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/a06fe8cfe3437685.
Report an issue: GitHub.