binarywang/WxJava · error · IllegalArgumentException

uri参数中不允许有access_token: {uri}

Error message

uri参数中不允许有access_token: {uri}

What it means

The Channel service's executeInternal refuses any URI that already contains the substring 'access_token='. The library is responsible for fetching and appending the access_token itself (line 234), so a caller-supplied token would be duplicated or stale and would leak the token into logs. This is a hard precondition enforced before any network call.

Source

Thrown at weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/BaseWxChannelServiceImpl.java:225

          } catch (InterruptedException e1) {
            Thread.currentThread().interrupt();
          }
        } else {
          throw e;
        }
      }
    } while (retryTimes++ < this.maxRetryTimes);

    log.warn("重试达到最大次数【{}】", this.maxRetryTimes);
    throw new WxRuntimeException("微信服务端异常,超出重试次数");
  }

  protected <T, E> T executeInternal(RequestExecutor<T, E> executor, String uri, E data, boolean doNotAutoRefreshToken,
                                     boolean printResult) throws WxErrorException {
    E dataForLog = DataUtils.handleDataWithSecret(data);

    if (uri.contains("access_token=")) {
      throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri);
    }
    String accessToken = getAccessToken(false);

    WxChannelConfig config = this.getConfig();
    if (StringUtils.isNotEmpty(config.getApiHostUrl())) {
      uri = uri.replace("https://api.weixin.qq.com", config.getApiHostUrl());
    }

    String uriWithAccessToken = uri + (uri.contains("?") ? "&" : "?") + "access_token=" + accessToken;

    try {
      T result = executor.execute(uriWithAccessToken, data, WxType.Channel);
      log.debug("\n【请求地址】: {}\n【请求参数】:{}\n【响应数据】:{}", uriWithAccessToken, dataForLog,
        printResult ? result : "...");
      return result;
    } catch (WxErrorException e) {
      WxError error = e.getError();
      if (WxConsts.ACCESS_TOKEN_ERROR_CODES.contains(error.getErrorCode())) {

View on GitHub (pinned to 1c43293a3c)

Solutions

  1. Pass only the path-and-query portion of the endpoint (e.g. /channel/eclyle/...), never including access_token.
  2. If you have a full URL, strip the access_token query parameter before handing it to the service.
  3. Audit any URI-building helpers to ensure they never append access_token; the SDK owns token injection.

Example fix

// before — caller appended token
String url = "https://api.weixin.qq.com/cgi-bin/...?access_token=" + token;
service.executeGet(url);

// after — pass clean path, SDK appends token
String url = "https://api.weixin.qq.com/cgi-bin/...";
service.executeGet(url);
Defensive patterns

Strategy: validation

Validate before calling

if (uri != null && uri.contains("access_token=")) {
  // strip any existing access_token param — the SDK appends its own
  uri = uri.replaceAll("([?&])access_token=[^&]*", "$1").replaceAll("[?&]$", "");
}
// now safe to pass to channelService

Try / catch

try {
  service.executeGet(uri);
} catch (IllegalArgumentException e) {
  if (e.getMessage().contains("access_token")) {
    // strip and retry, or fix the URI source
  }
  throw e;
}

Prevention

When it happens

Trigger: A caller passes a pre-built or cached URL that already includes '?access_token=...' (or '&access_token=...') into any WxChannelService execute/media/upload method.

Common situations: Copy-pasting a fully-formed WeChat endpoint URL from docs or a captured request; reusing a URL object that had the token appended by a previous call; building URIs with a helper that auto-adds the token.

Related errors


AI-assisted analysis of binarywang/WxJava@1c43293a3c (2026-08-14). Data as JSON: /api/errors/92f2712c0a43446a. Report an issue: GitHub.