binarywang/WxJava · warning · WxRuntimeException

受限于网络传输,起止时间的最大跨度为30天,如超过30天,则以结束时间为基准向前取30天进行查询

Error message

受限于网络传输,起止时间的最大跨度为30天,如超过30天,则以结束时间为基准向前取30天进行查询

What it means

Thrown (as unchecked WxRuntimeException) by getDialRecord() when the optional startTime/endTime pair spans 30 or more days (MONTH_SECONDS) or when endTime precedes startTime. WeChat's dial-record API caps the query window at strictly less than 30 days. Note the boundary uses >= (not >), so exactly 30 days is rejected.

Source

Thrown at weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOaServiceImpl.java:272

    JsonObject jsonObject = new JsonObject();

    if (offset == null) {
      offset = 0;
    }

    if (limit == null || limit <= 0) {
      limit = 100;
    }

    jsonObject.addProperty("offset", offset);
    jsonObject.addProperty("limit", limit);

    if (startTime != null && endTime != null) {
      long endtimestamp = endTime.getTime() / 1000L;
      long starttimestamp = startTime.getTime() / 1000L;

      if (endtimestamp - starttimestamp < 0 || endtimestamp - starttimestamp >= MONTH_SECONDS) {
        throw new WxRuntimeException("受限于网络传输,起止时间的最大跨度为30天,如超过30天,则以结束时间为基准向前取30天进行查询");
      }

      jsonObject.addProperty("start_time", starttimestamp);
      jsonObject.addProperty("end_time", endtimestamp);
    }

    final String url = this.mainService.getWxCpConfigStorage().getApiUrl(GET_DIAL_RECORD);
    String responseContent = this.mainService.post(url, jsonObject.toString());
    JsonObject tmpJson = GsonParser.parse(responseContent);

    return WxCpGsonBuilder.create().fromJson(tmpJson.get("record"),
      new TypeToken<List<WxCpDialRecord>>() {
      }.getType()
    );
  }

  @Override
  public WxCpOaApprovalTemplateResult getTemplateDetail(@NonNull String templateId) throws WxErrorException {

View on GitHub (pinned to 1c43293a3c)

Solutions

  1. Limit each query window to at most 29 days to stay safely under the boundary
  2. Chunk wide ranges into multiple sub-30-day calls
  3. Pass null for both startTime and endTime if you want the default recent window without time filtering

Example fix

// before
List<WxCpDialRecord> records = oaService.getDialRecord(userIds, null, monthStart, monthEnd, null, null); // exactly 30+ days

// after — keep window under 30 days
long maxWindow = 29L * 24 * 3600 * 1000;
Date safeEnd = new Date(Math.min(monthEnd.getTime(), monthStart.getTime() + maxWindow));
List<WxCpDialRecord> records = oaService.getDialRecord(userIds, null, monthStart, safeEnd, null, null);
Defensive patterns

Strategy: validation

Validate before calling

// Validate date range before calling getDialRecord
if (startTime != null && endTime != null) {
  long diff = (endTime.getTime() - startTime.getTime()) / 1000;
  if (diff < 0) {
    throw new IllegalArgumentException("endTime 必须晚于 startTime");
  }
  if (diff >= 31 * 24 * 3600) {
    // Chunk: use 29-day windows
    Date safeEnd = new Date(startTime.getTime() + 29L * 24 * 3600 * 1000);
    // call with safeEnd, then advance
  }
}

Prevention

When it happens

Trigger: Passing both startTime and endTime where the difference is negative or >= 2,678,400 seconds (31 days as defined by MONTH_SECONDS). The check is `endtimestamp - starttimestamp < 0 || endtimestamp - starttimestamp >= MONTH_SECONDS`. Only fires when both startTime and endTime are non-null.

Common situations: Querying a month's worth of call records without accounting for the strict < 30-day limit; passing a pre-built date range object; accidentally inverting start and end.

Related errors


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