{"record":{"id":"36e605b8e43f0157","repo":"justauth/JustAuth","slug":"data-getstring-description","errorCode":null,"errorMessage":"data.getString(\"description\")","messagePattern":"data\\.getString\\(\"description\"\\)","errorType":"exception","errorClass":"AuthException","httpStatus":null,"severity":"error","filePath":"src/main/java/me/zhyd/oauth/request/AuthDouyinRequest.java","lineNumber":80,"sourceCode":"    @Override\n    public AuthResponse<AuthToken> refresh(AuthToken oldToken) {\n        return AuthResponse.<AuthToken>builder()\n            .code(AuthResponseStatus.SUCCESS.getCode())\n            .data(getToken(refreshTokenUrl(oldToken.getRefreshToken())))\n            .build();\n    }\n\n    /**\n     * 检查响应内容是否正确\n     *\n     * @param object 请求响应内容\n     */\n    private void checkResponse(JSONObject object) {\n        String message = object.getString(\"message\");\n        JSONObject data = object.getJSONObject(\"data\");\n        int errorCode = data.getIntValue(\"error_code\");\n        if (\"error\".equals(message) || errorCode != 0) {\n            throw new AuthException(errorCode, data.getString(\"description\"));\n        }\n    }\n\n    /**\n     * 获取token，适用于获取access_token和刷新token\n     *\n     * @param accessTokenUrl 实际请求token的地址\n     * @return token对象\n     */\n    private AuthToken getToken(String accessTokenUrl) {\n        String response = new HttpUtils(config.getHttpConfig()).post(accessTokenUrl).getBody();\n        JSONObject object = JSONObject.parseObject(response);\n        this.checkResponse(object);\n        JSONObject dataObj = object.getJSONObject(\"data\");\n        return AuthToken.builder()\n            .accessToken(dataObj.getString(\"access_token\"))\n            .openId(dataObj.getString(\"open_id\"))\n            .expireIn(dataObj.getIntValue(\"expires_in\"))","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/justauth/JustAuth/blob/694bbf1b010d93404e3bfb4824d90e9ddfaebebb/src/main/java/me/zhyd/oauth/request/AuthDouyinRequest.java#L62-L98","documentation":"AuthDouyinRequest.checkResponse() treats a response as failed when the top-level 'message' is \"error\" or the nested data.error_code is non-zero, then throws AuthException(errorCode, description) with Douyin's own 'data.description' text. This guards both the token endpoint and the user-info endpoint.","triggerScenarios":"Token exchange or refresh with an invalid client_key/client_secret pair, or getUserInfo() with an access token that expired (Douyin tokens are short-lived) - Douyin returns message=\"error\" with a non-zero data.error_code.","commonSituations":"Douyin open-platform app in development/trial status so only whitelected test accounts can authorize; user's token revoked when they removed the app; or the client_key changed after the app was promoted from test to production.","solutions":["Log errorCode and description from the AuthException - Douyin's numeric codes (e.g. 2190008 for invalid client) pinpoint the cause.","Confirm client_key/client_secret and that the app has passed Douyin's review for the scopes you request.","Use the refresh token flow (refresh()) before calling getUserInfo() when access tokens have expired.","Ensure only whitelisted test users authorize while the app is in sandbox."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    return douyinRequest.getUserInfo(token);\n} catch (AuthException e) {\n    log.warn(\"Douyin error code={}, desc={}\", e.getErrorCode(), e.getErrorMsg());\n    if (e.getErrorCode() != 0) {\n        // map Douyin error_code to re-auth vs refresh decisions\n        return errorResponse(e.getErrorCode(), e.getErrorMsg());\n    }\n    throw e;\n}","preventionTips":["Whitelist test accounts while the Douyin app is in trial; otherwise all authorizations fail.","Implement refresh() before userinfo since Douyin access tokens are short-lived.","Log the numeric errorCode - Douyin's docs map codes to specific remediations."],"tags":["oauth","douyin","justauth","api-error","auth-exception"],"backgroundTag":null,"analyzedSha":"694bbf1b010d93404e3bfb4824d90e9ddfaebebb","analyzedAt":"2026-08-14T15:16:59.945Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}