{"record":{"id":"233d33de3d7a2f51","repo":"spring-projects/spring-security","slug":"server-error-233d33","errorCode":"server_error","errorMessage":"The token generator failed to generate the access token.","messagePattern":"The token generator failed to generate the access token\\.","errorType":"error_code","errorClass":"OAuth2AuthenticationException","httpStatus":400,"severity":"error","filePath":"oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationProvider.java","lineNumber":212,"sourceCode":"\t\t\t\t.authorizationServerContext(AuthorizationServerContextHolder.getContext())\n\t\t\t\t.authorization(authorization)\n\t\t\t\t.authorizedScopes(scopes)\n\t\t\t\t.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)\n\t\t\t\t.authorizationGrant(refreshTokenAuthentication);\n\t\t// @formatter:on\n\t\tif (dPoPProof != null) {\n\t\t\ttokenContextBuilder.put(OAuth2TokenContext.DPOP_PROOF_KEY, dPoPProof);\n\t\t}\n\n\t\tOAuth2Authorization.Builder authorizationBuilder = OAuth2Authorization.from(authorization);\n\n\t\t// ----- Access token -----\n\t\tOAuth2TokenContext tokenContext = tokenContextBuilder.tokenType(OAuth2TokenType.ACCESS_TOKEN).build();\n\t\tOAuth2Token generatedAccessToken = this.tokenGenerator.generate(tokenContext);\n\t\tif (generatedAccessToken == null) {\n\t\t\tOAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.SERVER_ERROR,\n\t\t\t\t\t\"The token generator failed to generate the access token.\", ERROR_URI);\n\t\t\tthrow new OAuth2AuthenticationException(error);\n\t\t}\n\n\t\tif (this.logger.isTraceEnabled()) {\n\t\t\tthis.logger.trace(\"Generated access token\");\n\t\t}\n\n\t\tOAuth2AccessToken accessToken = OAuth2AuthenticationProviderUtils.accessToken(authorizationBuilder,\n\t\t\t\tgeneratedAccessToken, tokenContext);\n\n\t\t// ----- Refresh token -----\n\t\tOAuth2RefreshToken currentRefreshToken = refreshToken.getToken();\n\t\tif (!registeredClient.getTokenSettings().isReuseRefreshTokens()) {\n\t\t\t// @formatter:off\n\t\t\ttokenContext = tokenContextBuilder\n\t\t\t\t\t.tokenType(OAuth2TokenType.REFRESH_TOKEN)\n\t\t\t\t\t.authorization(authorizationBuilder.build())\t// Refresh token generator/customizer may need access to the access token\n\t\t\t\t\t.build();\n\t\t\t// @formatter:on","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationProvider.java#L194-L230","documentation":"When refreshing tokens (grant_type=refresh_token), the provider requests a new access token from the composed OAuth2TokenGenerator. If generate() returns null for the ACCESS_TOKEN context — no supporting generator — a server_error OAuth2AuthenticationException with 'The token generator failed to generate the access token.' is thrown.","triggerScenarios":"OAuth2RefreshTokenAuthenticationProvider.authenticate() validating the refresh token and then generating: tokenGenerator.generate(access-token context) == null, typically because the configured generators don't match the client's access token format settings.","commonSituations":"Authorization server customized with tokenGenerator(new JwtGenerator(...)) only while the client's TokenSettings demand REFERENCE (opaque) tokens; vice versa with OAuth2AccessTokenGenerator only and SELF_CONTAINED required; upgrading Spring Authorization Server and dropping part of the default generator chain.","solutions":["Use DelegatingOAuth2TokenGenerator(JwtGenerator, OAuth2AccessTokenGenerator, OAuth2RefreshTokenGenerator) to cover all formats.","Match TokenSettings.getAccessTokenFormat() (SELF_CONTAINED/REFERENCE) of the RegisteredClient to the configured generators.","Verify custom generators return non-null for ACCESS_TOKEN token-type contexts.","Catch OAuth2AuthenticationException in the token endpoint and return the OAuth2Error (error=server_error) response."],"exampleFix":"// before\n.tokenGenerator(new OAuth2AccessTokenGenerator())  // client uses JWT\n// after\n.tokenGenerator(new DelegatingOAuth2TokenGenerator(\n    new JwtGenerator(encoder), new OAuth2AccessTokenGenerator()));","handlingStrategy":"try-catch","validationCode":"OAuth2TokenContext ctx = new OAuth2TokenContextBuilder()\n    .tokenType(OAuth2TokenType.ACCESS_TOKEN)\n    .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)\n    .registeredClient(registeredClient).build();\nif (tokenGenerator.generate(ctx) == null) {\n    throw new IllegalStateException(\"No generator produces access tokens for client \" + registeredClient.getId());\n}","typeGuard":null,"tryCatchPattern":"try {\n    Authentication result = provider.authenticate(refreshRequest);\n} catch (OAuth2AuthenticationException e) {\n    if (OAuth2ErrorCodes.SERVER_ERROR.equals(e.getError().getErrorCode())) {\n        // inspect tokenGenerator configuration before retrying\n        throw new IllegalStateException(\"Access token generator unsupported for this client\", e);\n    }\n    throw e;\n}","preventionTips":["After upgrading Spring Authorization Server, re-verify custom tokenGenerator() wiring still covers all token types.","Align each client's access token format setting with the deployed generator set.","Exercise the refresh_token grant in CI."],"tags":["oauth2","refresh-token-grant","access-token","token-generator"],"backgroundTag":"oauth-token-exchange-failed","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"}