{"record":{"id":"72c18957bf3cc5b5","repo":"theonedev/onedev","slug":"oauth-token-refresh-error-geterrormessage-error","errorCode":null,"errorMessage":"OAuth token refresh error: ${getErrorMessage(errorResponse.getErrorObject())}","messagePattern":"OAuth token refresh error: (.+?)","errorType":"exception","errorClass":"ExplicitException","httpStatus":null,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/util/oauth/DefaultOAuthTokenService.java","lineNumber":76,"sourceCode":"                new com.nimbusds.oauth2.sdk.token.RefreshToken(refreshTokenValue);\n        AuthorizationGrant refreshTokenGrant = new RefreshTokenGrant(refreshToken);\n\n        ClientAuthentication clientAuth = new ClientSecretBasic(\n                new ClientID(clientId), new Secret(clientSecret));\n\n        TokenResponse response;\n        try {\n            TokenRequest request = new TokenRequest(new URI(tokenEndpoint), clientAuth, refreshTokenGrant, null);\n            response = TokenResponse.parse(request.toHTTPRequest().send());\n        } catch (ParseException | URISyntaxException | IOException e) {\n            throw new RuntimeException(e);\n        }\n\n        if (response.indicatesSuccess()) {\n            return response.toSuccessResponse().getTokens();\n        } else {\n            TokenErrorResponse errorResponse = response.toErrorResponse();\n            throw new ExplicitException(getErrorMessage(errorResponse.getErrorObject()));\n        }\n\n    }\n\n    @Listen\n    public void on(SystemStarted event) {\n        taskId = taskScheduler.schedule(this);\n    }\n\n    @Listen\n    public void on(SystemStopping event) {\n        if (taskId != null)\n            taskScheduler.unschedule(taskId);\n    }\n\n    @Override\n    public void execute() {\n        accessTokenCache.entrySet().removeIf(it -> it.getValue().isExpired());","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/util/oauth/DefaultOAuthTokenService.java#L58-L94","documentation":"DefaultOAuthTokenService.requestTokens performs the OAuth token exchange/refresh against the authorization server. When the token endpoint returns a non-success response, the error object is converted to a message via getErrorMessage and thrown as ExplicitException (surfaced as 'OAuth token refresh error: ...'). This indicates the OAuth provider rejected the token request or refresh — e.g. invalid grant, bad client credentials, or expired refresh token.","triggerScenarios":"Calling requestTokens (via the tokens path) where the TokenResponse from the OAuth provider indicates failure: expired/revoked refresh token, wrong client_id/client_secret, redirect_uri mismatch, or the provider returning error codes like invalid_grant or invalid_client.","commonSituations":"Long-lived OAuth connections where the refresh token expired or was revoked; rotating the OAuth app's client secret without updating OneDev's server configuration; provider-side policy changes (token lifetimes, IP restrictions); clock skew invalidating tokens.","solutions":["Re-authorize the OAuth connection to obtain a fresh access/refresh token (re-run the login/link flow).","Read the provider error in the message (e.g. invalid_grant, invalid_client) and fix accordingly — usually re-consent or credential update.","Verify the OAuth app's client_id/client_secret and redirect URI configured on the server match the provider's settings.","Check provider status/docs for changed token policies and update server config, then retry."],"exampleFix":"// before: refresh token revoked -> invalid_grant on every refresh\n// after: re-authorize the account so a new refresh token is stored\n// Server admin: OAuth connection settings -> 'Authorize' again with the provider.","handlingStrategy":"try-catch","validationCode":"// Before refreshing, check stored token presence and expiry:\nboolean refreshPossible(OAuthToken token) {\n    return token != null && token.getRefreshToken() != null;\n}","typeGuard":null,"tryCatchPattern":"try {\n    tokens = oAuthTokenService.tokens(...);\n} catch (ExplicitException e) {\n    if (e.getMessage().startsWith(\"OAuth token refresh error\")) {\n        // trigger re-authorization flow for the connection\n    } else throw e;\n}","preventionTips":["Re-authorize OAuth connections periodically or when refresh tokens expire.","Keep client_id/client_secret/redirect URI in sync with the provider after rotation.","Monitor provider error codes (invalid_grant) and alert to prompt re-consent."],"tags":["oauth","token-refresh","http-error-response","authentication"],"backgroundTag":"oauth-token-exchange-failed","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}