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

  1. Check the errcode in the WxError: 40001 = invalid credential (secret wrong or revoked), 60020 = IP not whitelisted, 40013 = invalid corpId
  2. Verify the server's outbound IP is added to the WeChat Work admin console trusted IP list
  3. Ensure corpId and contactSecret are from the same corp and the secret has not been rotated
  4. Reduce token refresh frequency — the SDK caches tokens; avoid calling getContactAccessToken(true) unless necessary
  5. 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

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.