{"record":{"id":"aaaffd6664bf74b6","repo":"justauth/JustAuth","slug":"object-getstring-message-aaaffd","errorCode":null,"errorMessage":"object.getString(\"message\")","messagePattern":"object\\.getString\\(\"message\"\\)","errorType":"exception","errorClass":"AuthException","httpStatus":null,"severity":"error","filePath":"src/main/java/me/zhyd/oauth/request/AuthGitlabRequest.java","lineNumber":79,"sourceCode":"            .blog(object.getString(\"web_url\"))\n            .company(object.getString(\"organization\"))\n            .location(object.getString(\"location\"))\n            .email(object.getString(\"email\"))\n            .remark(object.getString(\"bio\"))\n            .gender(AuthUserGender.UNKNOWN)\n            .token(authToken)\n            .source(source.toString())\n            .build();\n    }\n\n    private void checkResponse(JSONObject object) {\n        // oauth/token 验证异常\n        if (object.containsKey(\"error\")) {\n            throw new AuthException(object.getString(\"error_description\"));\n        }\n        // user 验证异常\n        if (object.containsKey(\"message\")) {\n            throw new AuthException(object.getString(\"message\"));\n        }\n    }\n\n    /**\n     * 返回带{@code state}参数的授权url，授权回调时会带上这个{@code state}\n     *\n     * @param state state 验证授权流程的参数，可以防止csrf\n     * @return 返回授权地址\n     * @since 1.11.0\n     */\n    @Override\n    public String authorize(String state) {\n        return UrlBuilder.fromBaseUrl(super.authorize(state))\n            .queryParam(\"scope\", this.getScopes(\"+\", false, AuthScopeUtils.getDefaultScopes(AuthGitlabScope.values())))\n            .build();\n    }\n\n}","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/justauth/JustAuth/blob/694bbf1b010d93404e3bfb4824d90e9ddfaebebb/src/main/java/me/zhyd/oauth/request/AuthGitlabRequest.java#L61-L97","documentation":"Second branch of AuthGitlabRequest.checkResponse(): GitLab's REST/user API reports failures with a top-level 'message' key (e.g. {\"message\":\"401 Unauthorized\"}), and this branch throws AuthException carrying that message. It typically fires on the userinfo call with a bad or expired access token.","triggerScenarios":"getUserInfo() with an access token that expired (GitLab tokens default to 2 hours), was revoked, or was issued by a different GitLab instance/application than the one being queried.","commonSituations":"Session outliving the 2-hour token lifetime without refresh; self-hosted GitLab behind a proxy that strips the Authorization header; or a Personal Access Token mistakenly configured where an OAuth token was expected.","solutions":["Call refresh() with the stored refresh token when the message is 401/403, then retry getUserInfo().","Check that the token in AuthToken came from the same GitLab instance defined in AuthSource.accessToken().","Verify any reverse proxy forwards the Authorization header untouched to GitLab.","Persist refresh tokens at login; GitLab issues them with a longer lifetime than access tokens."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    return gitlabRequest.getUserInfo(token);\n} catch (AuthException e) {\n    String m = String.valueOf(e.getErrorMsg());\n    if (m.contains(\"401\") || m.contains(\"403\")) {\n        AuthResponse r = gitlabRequest.refresh(AuthToken.builder().refreshToken(refreshToken).build());\n        if (r.ok()) { return gitlabRequest.getUserInfo((AuthToken) r.getData()); }\n        return redirectToReauthorize();\n    }\n    throw e;\n}","preventionTips":["GitLab access tokens expire in about 2 hours - refresh before each userinfo call in long sessions.","Check proxy config forwards the Authorization header to self-hosted GitLab.","Never mix tokens across GitLab instances; store the source with the token."],"tags":["oauth","gitlab","justauth","api-error","token-expired"],"backgroundTag":null,"analyzedSha":"694bbf1b010d93404e3bfb4824d90e9ddfaebebb","analyzedAt":"2026-08-14T15:16:59.945Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}