binarywang/WxJava · error · WxErrorException

上传失败,服务器响应空 url:%s param:%s

Error message

上传失败,服务器响应空 url:%s param:%s

What it means

The Apache HttpClient (4.x) upload executor throws when the server returns an empty response body after a multipart POST. An empty body cannot be parsed into a WxError, so the executor fails fast with the request URL and param for diagnostics. This indicates the request reached a server but got a non-JSON/empty reply rather than a WeChat error envelope.

Source

Thrown at weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutorApacheImpl.java:64

      InnerStreamBody part = new InnerStreamBody(data.getInputStream(), ContentType.DEFAULT_BINARY, data.getFileName(), data.getLength());
      MultipartEntityBuilder entityBuilder = MultipartEntityBuilder
        .create()
        .addPart(param.getName(), part)
        .setMode(HttpMultipartMode.RFC6532);

      // 添加额外的表单字段
      if (param.getFormFields() != null && !param.getFormFields().isEmpty()) {
        for (java.util.Map.Entry<String, String> entry : param.getFormFields().entrySet()) {
          entityBuilder.addTextBody(entry.getKey(), entry.getValue(), ContentType.TEXT_PLAIN.withCharset("UTF-8"));
        }
      }

      HttpEntity entity = entityBuilder.build();
      httpPost.setEntity(entity);
    }
    String responseContent = requestHttp.getRequestHttpClient().execute(httpPost, Utf8ResponseHandler.INSTANCE);
    if (StringUtils.isEmpty(responseContent)) {
      throw new WxErrorException(String.format("上传失败,服务器响应空 url:%s param:%s", uri, param));
    }
    WxError error = WxError.fromJson(responseContent, wxType);
    if (error.getErrorCode() != 0) {
      throw new WxErrorException(error);
    }
    return responseContent;
  }

  /**
   * 内部流 请求体
   */
  @Getter
  public static class InnerStreamBody extends InputStreamBody {

    private final long contentLength;

    public InnerStreamBody(final InputStream in, final ContentType contentType, final String filename, long contentLength) {
      super(in, contentType, filename);

View on GitHub (pinned to 1c43293a3c)

Solutions

  1. Verify apiHostUrl (if set) routes correctly and does not strip responses.
  2. Retry the upload once — empty responses are often transient infra glitches.
  3. Capture the raw HTTP exchange (status code + headers) to distinguish gateway/WAF behaviour from a WeChat-side issue.
  4. Confirm the upload payload size is within WeChat's documented limits for the endpoint.

Example fix

// before — single shot, surfaces empty-response error
String url = service.upload(param);

// after — retry once on empty-response
try {
  return service.upload(param);
} catch (WxErrorException e) {
  if (e.getMessage() != null && e.getMessage().contains("服务器响应空")) {
    return service.upload(param); // one retry
  }
  throw e;
}
Defensive patterns

Strategy: retry

Try / catch

int attempts = 0;
while (true) {
  try {
    return service.upload(param);
  } catch (WxErrorException e) {
    boolean empty = e.getMessage() != null && e.getMessage().contains("服务器响应空");
    if (!empty || ++attempts > 2) throw e;
    Thread.sleep(1000L * attempts);
  }
}

Prevention

When it happens

Trigger: WeChat (or a configured apiHostUrl proxy) returns HTTP 200 with an empty body; a gateway/WAF strips the response; a network device closes the connection returning nothing; the endpoint URL is wrong and an intermediary returns an empty page.

Common situations: Misconfigured apiHostUrl pointing to a proxy that returns empty; large upload hitting an upstream body-size limit that silently drops the response; transient infra issue; wrong endpoint path returning an HTML error page that the client reads as empty after charset handling.

Related errors


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