{"record":{"id":"a06fe8cfe3437685","repo":"spring-projects/spring-security","slug":"authenticationexception-must-be-of-type-s-but-was","errorCode":null,"errorMessage":"AuthenticationException must be of type %s but was %s","messagePattern":"AuthenticationException must be of type (.+?) but was (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2ErrorAuthenticationFailureHandler.java","lineNumber":65,"sourceCode":"public final class OAuth2ErrorAuthenticationFailureHandler implements AuthenticationFailureHandler {\n\n\tprivate final Log logger = LogFactory.getLog(getClass());\n\n\tprivate HttpMessageConverter<OAuth2Error> errorResponseConverter = new OAuth2ErrorHttpMessageConverter();\n\n\t@Override\n\tpublic void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,\n\t\t\tAuthenticationException authenticationException) throws IOException, ServletException {\n\t\tServletServerHttpResponse httpResponse = new ServletServerHttpResponse(response);\n\t\thttpResponse.setStatusCode(HttpStatus.BAD_REQUEST);\n\n\t\tif (authenticationException instanceof OAuth2AuthenticationException oauth2AuthenticationException) {\n\t\t\tOAuth2Error error = oauth2AuthenticationException.getError();\n\t\t\tthis.errorResponseConverter.write(error, null, httpResponse);\n\t\t}\n\t\telse {\n\t\t\tif (this.logger.isWarnEnabled()) {\n\t\t\t\tthis.logger.warn(AuthenticationException.class.getSimpleName() + \" must be of type \"\n\t\t\t\t\t\t+ OAuth2AuthenticationException.class.getName() + \" but was \"\n\t\t\t\t\t\t+ authenticationException.getClass().getName());\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Sets the {@link HttpMessageConverter} used for converting an {@link OAuth2Error} to\n\t * an HTTP response.\n\t * @param errorResponseConverter the {@link HttpMessageConverter} used for converting\n\t * an {@link OAuth2Error} to an HTTP response\n\t */\n\tpublic void setErrorResponseConverter(HttpMessageConverter<OAuth2Error> errorResponseConverter) {\n\t\tAssert.notNull(errorResponseConverter, \"errorResponseConverter cannot be null\");\n\t\tthis.errorResponseConverter = errorResponseConverter;\n\t}\n\n}","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2ErrorAuthenticationFailureHandler.java#L47-L83","documentation":"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.","triggerScenarios":"Registering an OAuth2ErrorAuthenticationFailureHandler on an authentication filter/endpoint where a non-OAuth2 AuthenticationException (e.g. BadCredentialsException, UsernameNotFoundException, DisabledException) can be thrown.","commonSituations":"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.","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"],"exampleFix":"// before\nthrow new BadCredentialsException(\"invalid token\");\n// after\nthrow new OAuth2AuthenticationException(new OAuth2Error(\"invalid_token\", \"invalid token\", null));","handlingStrategy":"type-guard","validationCode":"if (!(ex instanceof OAuth2AuthenticationException)) {\n    logger.warn(\"Non-OAuth2 AuthenticationException routed to OAuth2ErrorAuthenticationFailureHandler: \" + ex.getClass().getName());\n}","typeGuard":"if (authenticationException instanceof OAuth2AuthenticationException oauth2Ex) {\n    // safe: handler can render oauth2Ex.getError()\n}","tryCatchPattern":"try {\n    filterChain.doFilter(request, response);\n} catch (AuthenticationException ex) {\n    OAuth2Error error = (ex instanceof OAuth2AuthenticationException o) ? o.getError()\n        : new OAuth2Error(\"server_error\", ex.getMessage(), null);\n    // write error via converter\n}","preventionTips":["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"],"tags":["oauth2","authentication","handler","spring-security"],"backgroundTag":"type-mismatch","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}