{"record":{"id":"d326a8b65a5b6067","repo":"justauth/JustAuth","slug":"object-getstring-sub-error-object-getst-d326a8","errorCode":null,"errorMessage":"object.getString(\"sub_error\") + \":\" + object.getString(\"error_description\")","messagePattern":"object\\.getString\\(\"sub_error\"\\) \\+ \":\" \\+ object\\.getString\\(\"error_description\"\\)","errorType":"exception","errorClass":"AuthException","httpStatus":null,"severity":"error","filePath":"src/main/java/me/zhyd/oauth/request/AuthHuaweiV3Request.java","lineNumber":191,"sourceCode":"            builder.queryParam(\"code_challenge\", codeChallenge)\n                .queryParam(\"code_challenge_method\", codeChallengeMethod);\n            // 缓存 codeVerifier 十分钟\n            this.authStateCache.cache(cacheKey, codeVerifier, TimeUnit.MINUTES.toMillis(10));\n        }\n        return builder.build();\n    }\n\n    /**\n     * 校验响应结果\n     *\n     * @param object 接口返回的结果\n     */\n    private void checkResponse(JSONObject object) {\n        if (object.containsKey(\"NSP_STATUS\")) {\n            throw new AuthException(object.getString(\"error\"));\n        }\n        if (object.containsKey(\"error\")) {\n            throw new AuthException(object.getString(\"sub_error\") + \":\" + object.getString(\"error_description\"));\n        }\n    }\n\n\n}\n","sourceCodeStart":173,"sourceCodeEnd":197,"githubUrl":"https://github.com/justauth/JustAuth/blob/694bbf1b010d93404e3bfb4824d90e9ddfaebebb/src/main/java/me/zhyd/oauth/request/AuthHuaweiV3Request.java#L173-L197","documentation":"Second branch of AuthHuaweiV3Request.checkResponse: when the response JSON contains an 'error' key, JustAuth throws AuthException with 'sub_error:error_description' concatenated. This is the standard OAuth2 error shape Huawei returns for grant failures (bad code, invalid client, missing scope).","triggerScenarios":"Any Huawei V3 token or refresh call whose response body includes an 'error' object/field, e.g. invalid_grant on code replay, invalid_client on secret mismatch, or missing open scope permissions.","commonSituations":"Expired or reused authorization code, wrong client secret, requesting scopes (e.g. getAvatar) not enabled for the app, or clock skew causing the code to appear expired.","solutions":["Read the sub_error/error_description pair in the exception message: invalid_grant means get a new code; invalid_client means fix credentials","Ensure the authorization URL was built from the same clientId used in the token exchange","Check that requested scopes are approved for the app in AppGallery Connect","Catch AuthException at the login endpoint and redirect the user to re-authorize"],"exampleFix":"null","handlingStrategy":"try-catch","validationCode":"null","typeGuard":"null","tryCatchPattern":"try {\n    huaweiRequest.getAuthResponse(callback);\n} catch (AuthException e) {\n    // message pattern: sub_error:error_description\n    String[] parts = String.valueOf(e.getMessage()).split(\":\", 2);\n    if (parts[0].contains(\"invalid_grant\")) { /* restart OAuth flow */ }\n}","preventionTips":["Exchange the authorization code immediately (Huawei codes expire in minutes)","Only request scopes enabled for the app in AppGallery Connect","Differentiate invalid_client (fix secret) from invalid_grant (new code) before retrying"],"tags":["oauth","huawei","invalid-grant","auth-exception"],"backgroundTag":null,"analyzedSha":"694bbf1b010d93404e3bfb4824d90e9ddfaebebb","analyzedAt":"2026-08-14T15:16:59.945Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}