binarywang/WxJava · error · WxErrorException
错误代码:{}, 错误信息:{}
Error message
错误代码:{}, 错误信息:{} What it means
Thrown (as checked WxErrorException wrapping a WxError) when the WeChat API returns a non-zero error code during contact access_token retrieval via the Jodd HTTP implementation. Unlike the secret-not-configured error (which fires before the HTTP call), this fires after the API responds with an error. The message is formatted by WxError.toString() as '错误代码:{code}, 错误信息:{msg}'.
Source
Thrown at weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceJoddHttpImpl.java:97
return this.configStorage.getContactAccessToken();
}
// 使用通讯录同步secret获取access_token
String contactSecret = this.configStorage.getContactSecret();
if (contactSecret == null || contactSecret.trim().isEmpty()) {
throw new WxErrorException("通讯录同步secret未配置");
}
HttpRequest request = HttpRequest.get(String.format(this.configStorage.getApiUrl(WxCpApiPathConsts.GET_TOKEN),
this.configStorage.getCorpId(), contactSecret));
if (this.httpProxy != null) {
httpClient.useProxy(this.httpProxy);
}
request.withConnectionProvider(httpClient);
HttpResponse response = request.send();
String resultContent = response.bodyText();
WxError error = WxError.fromJson(resultContent, WxType.CP);
if (error.getErrorCode() != 0) {
throw new WxErrorException(error);
}
WxAccessToken accessToken = WxAccessToken.fromJson(resultContent);
this.configStorage.updateContactAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn());
} finally {
lock.unlock();
}
return this.configStorage.getContactAccessToken();
}
@Override
public String getMsgAuditAccessToken(boolean forceRefresh) throws WxErrorException {
if (!this.configStorage.isMsgAuditAccessTokenExpired() && !forceRefresh) {
return this.configStorage.getMsgAuditAccessToken();
}
Lock lock = this.configStorage.getMsgAuditAccessTokenLock();
lock.lock();
try {View on GitHub (pinned to 1c43293a3c)
Solutions
- Check the errcode in the WxError: 40001 = invalid credential (secret wrong or revoked), 60020 = IP not whitelisted, 40013 = invalid corpId
- Verify the server's outbound IP is added to the WeChat Work admin console trusted IP list
- Ensure corpId and contactSecret are from the same corp and the secret has not been rotated
- Reduce token refresh frequency — the SDK caches tokens; avoid calling getContactAccessToken(true) unless necessary
- Log the full WxError.getJson() for the raw WeChat response to diagnose edge cases
Example fix
// before — calling force refresh unnecessarily, or with stale secret
String token = service.getContactAccessToken(true); // may hit rate limit or invalid credential
// after — let the SDK manage token lifecycle, and handle errors with diagnostics
try {
String token = service.getContactAccessToken(false); // use cached token
} catch (WxErrorException e) {
WxError err = e.getError();
log.error("获取通讯录 token 失败 errcode={}, errmsg={}, raw={}",
err.getErrorCode(), err.getErrorMsg(), err.getJson());
if (err.getErrorCode() == 60020) {
log.error("当前服务器 IP 未加入企业微信可信 IP 列表");
}
throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-validate that secrets are set and IP is whitelisted before requesting token
String contactSecret = configStorage.getContactSecret();
if (StringUtils.isBlank(contactSecret)) {
throw new IllegalStateException("通讯录同步 secret 未配置");
}
// Ensure the server IP is in the WeChat admin trusted IP list (manual check) Try / catch
try {
String token = service.getContactAccessToken(false);
} catch (WxErrorException e) {
WxError error = e.getError();
switch (error.getErrorCode()) {
case 40001:
log.error("凭证无效:contactSecret 可能已失效或被更换");
break;
case 60020:
log.error("当前 IP 不在企业微信可信 IP 列表中,请添加: {}", serverIp);
break;
case 40013:
log.error("corpId 无效");
break;
default:
log.error("获取通讯录 token 失败: {}", error.toString());
}
throw e;
} Prevention
- Add the server's outbound IP to the WeChat Work admin console trusted IP list before deploying
- Avoid calling getContactAccessToken(true) unless the cached token is confirmed expired — let the SDK manage refresh
- Monitor for secret rotation in the WeChat admin console and update config promptly
- Log the full WxError (including raw JSON) for diagnostics when token retrieval fails
- Ensure corpId, corpSecret, and contactSecret are all from the same WeChat Work corp
When it happens
Trigger: The HTTP GET to the token endpoint succeeds but the response JSON contains errcode != 0. Common causes: invalid corpId or contactSecret (errcode 40001), IP not in the whitelist (errcode 60020), the contact secret was revoked in the admin console, or rate limiting on token refresh.
Common situations: The contact secret was rotated in the WeChat admin console but the app still uses the old value; the server IP is not in the API whitelist; corpId and secret are mismatched (from different corps); excessive token refresh calls hitting the rate limit; the contact-sync app was disabled in the admin console.
Related errors
AI-assisted analysis of binarywang/WxJava@1c43293a3c (2026-08-14).
Data as JSON: /api/errors/5af829feef4c4d31.
Report an issue: GitHub.