{"record":{"id":"f23053d73f84ba5a","repo":"justauth/JustAuth","slug":"errorcode","errorCode":"${errorCode}","errorMessage":"${errorMsg}","messagePattern":"\\$\\{errorMsg\\}","errorType":"exception","errorClass":"AuthException","httpStatus":null,"severity":"error","filePath":"src/main/java/me/zhyd/oauth/request/AuthWechatMiniProgramRequest.java","lineNumber":70,"sourceCode":"        // 如果需要用户信息，需要在小程序调用函数后传给后端\n        return AuthUser.builder()\n            .username(\"\")\n            .nickname(\"\")\n            .avatar(\"\")\n            .uuid(authToken.getOpenId())\n            .token(authToken)\n            .source(source.toString())\n            .build();\n    }\n\n    /**\n     * 检查响应内容是否正确\n     *\n     * @param response 请求响应内容\n     */\n    private void checkResponse(JSCode2SessionResponse response) {\n        if (response.getErrorCode() != 0) {\n            throw new AuthException(response.getErrorCode(), response.getErrorMsg());\n        }\n    }\n\n    @Override\n    protected String accessTokenUrl(String code) {\n        return UrlBuilder.fromBaseUrl(source.accessToken())\n            .queryParam(\"appid\", config.getClientId())\n            .queryParam(\"secret\", config.getClientSecret())\n            .queryParam(\"js_code\", code)\n            .queryParam(\"grant_type\", \"authorization_code\")\n            .build();\n    }\n\n    @Data\n    @SuppressWarnings(\"SpellCheckingInspection\")\n    private static class JSCode2SessionResponse {\n\n        @JSONField(name = \"errcode\")","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/justauth/JustAuth/blob/694bbf1b010d93404e3bfb4824d90e9ddfaebebb/src/main/java/me/zhyd/oauth/request/AuthWechatMiniProgramRequest.java#L52-L88","documentation":"AuthWechatMiniProgramRequest.checkResponse takes the deserialized JSCode2SessionResponse (from the jscode2session endpoint of a WeChat Mini Program) and throws AuthException(errorCode, errorMsg) whenever errorCode != 0. The exception's numeric code is WeChat's own error code, the message its errmsg. Note it triggers only on non-zero codes — a successful session returns 0/absent code.","triggerScenarios":"jscode2session call failing: invalid js_code from wx.login() (40029 — already used, expired ~5min, or from a different mini program), invalid appid/secret pairing (40125), IP not in the mini program's whitelist (40164), or rate limiting (45011).","commonSituations":"Frontend calls wx.login() but the code is sent to the backend twice (duplicate HTTP retry) — second exchange returns 40029; appid of the mini program mixed up with the official account's appid; backend deployed to a new IP without updating the whitelist; dev tools issuing codes for a different environment.","solutions":["Check e.getCode(): 40029 → dedupe js_code submissions (idempotency key on the login endpoint); 40164 → whitelist the backend IP in the mini program console (开发管理>开发设置>服务器域名/IP名单); 40125 → fix the appsecret.","Ensure AuthConfig uses the mini program's AppID + AppSecret pair, not the bound official account's.","Submit js_code to your backend immediately and exchange it once; treat code as single-use.","Cache session_key/openid per openid instead of re-running jscode2session."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// idempotent login endpoint: one js_code, one exchange\nString key = \"jscode:\" + req.getJsCode();\nif (!redis.setnx(key, \"1\", Duration.ofMinutes(10))) {\n    return cachedSession(req.getJsCode()); // duplicate submit\n}","typeGuard":null,"tryCatchPattern":"try {\n    AuthUser u = mpRequest.login(callback);\n} catch (AuthException e) {\n    switch (e.getCode()) {\n        case 40029: return ResponseEntity.status(409).body(\"code already used or invalid, call wx.login() again\");\n        case 40164: throw new ConfigurationException(\"whitelist backend IP\", e);\n        case 40125: throw new ConfigurationException(\"check mini-program appSecret\", e);\n        default: throw e;\n    }\n}","preventionTips":["Make the client re-run wx.login() on 40029 instead of resubmitting the same code.","Use the mini program's own AppID/AppSecret, never the bound official account's.","Keep the backend IP whitelist updated when infrastructure changes."],"tags":["justauth","wechat-miniprogram","jscode2session","code-reuse","ip-whitelist"],"backgroundTag":null,"analyzedSha":"694bbf1b010d93404e3bfb4824d90e9ddfaebebb","analyzedAt":"2026-08-14T15:16:59.945Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}