{"record":{"id":"290445afc96f2aa7","repo":"justauth/JustAuth","slug":"errcode","errorCode":"${errcode}","errorMessage":"${errmsg}","messagePattern":"\\$\\{errmsg\\}","errorType":"exception","errorClass":"AuthException","httpStatus":null,"severity":"error","filePath":"src/main/java/me/zhyd/oauth/request/AuthWeChatMpRequest.java","lineNumber":96,"sourceCode":"            .build();\n    }\n\n    @Override\n    public AuthResponse<AuthToken> refresh(AuthToken oldToken) {\n        return AuthResponse.<AuthToken>builder()\n            .code(AuthResponseStatus.SUCCESS.getCode())\n            .data(this.getToken(refreshTokenUrl(oldToken.getRefreshToken())))\n            .build();\n    }\n\n    /**\n     * 检查响应内容是否正确\n     *\n     * @param object 请求响应内容\n     */\n    private void checkResponse(JSONObject object) {\n        if (object.containsKey(\"errcode\")) {\n            throw new AuthException(object.getIntValue(\"errcode\"), object.getString(\"errmsg\"));\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()).get(accessTokenUrl).getBody();\n        JSONObject accessTokenObject = JSONObject.parseObject(response);\n\n        this.checkResponse(accessTokenObject);\n\n        return AuthToken.builder()\n            .accessToken(accessTokenObject.getString(\"access_token\"))\n            .refreshToken(accessTokenObject.getString(\"refresh_token\"))","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/justauth/JustAuth/blob/694bbf1b010d93404e3bfb4824d90e9ddfaebebb/src/main/java/me/zhyd/oauth/request/AuthWeChatMpRequest.java#L78-L114","documentation":"AuthWeChatMpRequest.checkResponse is the guard for WeChat Official Account (公众号) mini-program-style token endpoints: if the JSON contains `errcode`, it throws AuthException(int code, String msg) where the exception's numeric code is WeChat's own errcode and the message is errmsg. So unlike source-tagged exceptions, this one surfaces the raw WeChat error code (e.g. 40029, 40164, 45011).","triggerScenarios":"jscode2session-style token fetch or refresh in the WeChat MP flow failing: invalid js_code (40029), invalid appsecret (40125), IP not in whitelist (40164), api daily quota (45011), or invalid grant_type on refresh (40029/41008).","commonSituations":"Server IP not added to the official account's IP whitelist (40164 is extremely common on first deploy); appid/appsecret from a different account or reset after regeneration; authorization code (js_code) used twice or expired; hitting WeChat API rate limits during load tests.","solutions":["Map the exception's code via WeChat's global error-code table: 40164 → add the server's egress IP to IP whitelist in the MP console; 40125 → fix appsecret; 40029 → js_code invalid/reused; 45011 → rate limited, back off.","Verify AuthConfig.clientId=appId and clientSecret=appSecret belong to the same Official Account.","Cache the fetched access_token (it is valid ~2h) instead of re-requesting per call to avoid 45011.","Log e.getCode() numerically in your monitoring and alert on 40164 specifically after infra/IP changes."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// verify the egress IP is likely whitelisted before first deploy\nString ip = new HttpUtils(null).get(\"https://httpbin.org/ip\").getBody();\nlog.info(\"egress IP to whitelist in WeChat MP console: {}\", ip);\nAssert.hasText(config.getClientId(), \"appId required\");\nAssert.hasText(config.getClientSecret(), \"appSecret required\");","typeGuard":null,"tryCatchPattern":"try {\n    return mpRequest.getAccessToken(callback);\n} catch (AuthException e) {\n    switch (e.getCode()) {\n        case 40164: throw new ConfigurationException(\"whitelist server IP in WeChat MP console\", e);\n        case 45011: backoffAndRetryOnce(); break; // rate limited\n        case 40029: throw new InvalidGrantException(\"js_code reused/expired\", e);\n        default: throw e;\n    }\n}","preventionTips":["Add every deployment environment's egress IP to the MP console whitelist at infra-provisioning time.","Cache access_token for ~7000s and reuse it rather than re-fetching.","Alert on WeChat errcodes 40164/45011 in production monitoring."],"tags":["justauth","wechat-mp","official-account","errcode","ip-whitelist"],"backgroundTag":null,"analyzedSha":"694bbf1b010d93404e3bfb4824d90e9ddfaebebb","analyzedAt":"2026-08-14T15:16:59.945Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}