{"record":{"id":"e8618251197ebc26","repo":"justauth/JustAuth","slug":"object-getstring-msg-e86182","errorCode":null,"errorMessage":"object.getString(\"msg\")","messagePattern":"object\\.getString\\(\"msg\"\\)","errorType":"exception","errorClass":"AuthException","httpStatus":null,"severity":"error","filePath":"src/main/java/me/zhyd/oauth/request/AuthQqRequest.java","lineNumber":53,"sourceCode":"    @Override\n    public AuthToken getAccessToken(AuthCallback authCallback) {\n        String response = doGetAuthorizationCode(authCallback.getCode());\n        return getAuthToken(response);\n    }\n\n    @Override\n    public AuthResponse<AuthToken> refresh(AuthToken authToken) {\n        String response = new HttpUtils(config.getHttpConfig()).get(refreshTokenUrl(authToken.getRefreshToken())).getBody();\n        return AuthResponse.<AuthToken>builder().code(AuthResponseStatus.SUCCESS.getCode()).data(getAuthToken(response)).build();\n    }\n\n    @Override\n    public AuthUser getUserInfo(AuthToken authToken) {\n        String openId = this.getOpenId(authToken);\n        String response = doGetUserInfo(authToken);\n        JSONObject object = JSONObject.parseObject(response);\n        if (object.getIntValue(\"ret\") != 0) {\n            throw new AuthException(object.getString(\"msg\"));\n        }\n        String avatar = object.getString(\"figureurl_qq_2\");\n        if (StringUtils.isEmpty(avatar)) {\n            avatar = object.getString(\"figureurl_qq_1\");\n        }\n\n        String location = String.format(\"%s-%s\", object.getString(\"province\"), object.getString(\"city\"));\n        return AuthUser.builder()\n            .rawUserInfo(object)\n            .username(object.getString(\"nickname\"))\n            .nickname(object.getString(\"nickname\"))\n            .avatar(avatar)\n            .location(location)\n            .uuid(openId)\n            .gender(AuthUserGender.getRealGender(object.getString(\"gender\")))\n            .token(authToken)\n            .source(source.toString())\n            .build();","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/justauth/JustAuth/blob/694bbf1b010d93404e3bfb4824d90e9ddfaebebb/src/main/java/me/zhyd/oauth/request/AuthQqRequest.java#L35-L71","documentation":"AuthQqRequest.getUserInfo throws AuthException with the 'msg' field when the QQ user-info response has ret != 0. QQ returns ret=0 for success; non-zero ret codes (100030, 100016, etc.) indicate the user profile call failed.","triggerScenarios":"Calling getUserInfo after getOpenId when QQ's /user/get_user_info returns ret!=0 — typically an expired/invalid access token (100016) or a missing scope/permission for profile data.","commonSituations":"Access token expired (QQ tokens are short-lived), the app lacks the get_user_info scope, or unionid/openid mismatch from mixing app types.","solutions":["Map the ret code: 100016 = token expired → refresh via refresh token; 100030 = no permission → request get_user_info scope in authorize URL","Ensure getScopes in authorize includes get_user_info","Call refresh() when the token approaches expiry before getUserInfo","Log the 'msg' string, QQ often includes the Chinese reason"],"exampleFix":"null","handlingStrategy":"retry","validationCode":"if (System.currentTimeMillis() > issuedAtMs + token.getExpiresIn() * 1000L) {\n    token = qqRequest.refresh(token).getData();\n}","typeGuard":"null","tryCatchPattern":"try {\n    return qqRequest.getUserInfo(token);\n} catch (AuthException e) {\n    // ret 100016 → token expired: refresh and retry once\n    token = qqRequest.refresh(token).getData();\n    return qqRequest.getUserInfo(token);\n}","preventionTips":["Include get_user_info in the authorize scope list","Refresh QQ tokens before expiry instead of on failure","Map ret codes (100016/100030) to user-facing actions"],"tags":["oauth","qq","token-expired","scope","auth-exception"],"backgroundTag":null,"analyzedSha":"694bbf1b010d93404e3bfb4824d90e9ddfaebebb","analyzedAt":"2026-08-14T15:16:59.945Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}