{"record":{"id":"c0052c4d9db5835e","repo":"binarywang/WxJava","slug":"url-s-param-s","errorCode":null,"errorMessage":"上传失败，服务器响应空 url:%s param:%s","messagePattern":"上传失败，服务器响应空 url:(.+?) param:(.+?)","errorType":"exception","errorClass":"WxErrorException","httpStatus":null,"severity":"error","filePath":"weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutorApacheImpl.java","lineNumber":64,"sourceCode":"      InnerStreamBody part = new InnerStreamBody(data.getInputStream(), ContentType.DEFAULT_BINARY, data.getFileName(), data.getLength());\n      MultipartEntityBuilder entityBuilder = MultipartEntityBuilder\n        .create()\n        .addPart(param.getName(), part)\n        .setMode(HttpMultipartMode.RFC6532);\n\n      // 添加额外的表单字段\n      if (param.getFormFields() != null && !param.getFormFields().isEmpty()) {\n        for (java.util.Map.Entry<String, String> entry : param.getFormFields().entrySet()) {\n          entityBuilder.addTextBody(entry.getKey(), entry.getValue(), ContentType.TEXT_PLAIN.withCharset(\"UTF-8\"));\n        }\n      }\n\n      HttpEntity entity = entityBuilder.build();\n      httpPost.setEntity(entity);\n    }\n    String responseContent = requestHttp.getRequestHttpClient().execute(httpPost, Utf8ResponseHandler.INSTANCE);\n    if (StringUtils.isEmpty(responseContent)) {\n      throw new WxErrorException(String.format(\"上传失败，服务器响应空 url:%s param:%s\", uri, param));\n    }\n    WxError error = WxError.fromJson(responseContent, wxType);\n    if (error.getErrorCode() != 0) {\n      throw new WxErrorException(error);\n    }\n    return responseContent;\n  }\n\n  /**\n   * 内部流 请求体\n   */\n  @Getter\n  public static class InnerStreamBody extends InputStreamBody {\n\n    private final long contentLength;\n\n    public InnerStreamBody(final InputStream in, final ContentType contentType, final String filename, long contentLength) {\n      super(in, contentType, filename);","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/binarywang/WxJava/blob/1c43293a3c2c9d7e91304b6d037fb017f680d0c6/weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutorApacheImpl.java#L46-L82","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Verify apiHostUrl (if set) routes correctly and does not strip responses.","Retry the upload once — empty responses are often transient infra glitches.","Capture the raw HTTP exchange (status code + headers) to distinguish gateway/WAF behaviour from a WeChat-side issue.","Confirm the upload payload size is within WeChat's documented limits for the endpoint."],"exampleFix":"// before — single shot, surfaces empty-response error\nString url = service.upload(param);\n\n// after — retry once on empty-response\ntry {\n  return service.upload(param);\n} catch (WxErrorException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"服务器响应空\")) {\n    return service.upload(param); // one retry\n  }\n  throw e;\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"int attempts = 0;\nwhile (true) {\n  try {\n    return service.upload(param);\n  } catch (WxErrorException e) {\n    boolean empty = e.getMessage() != null && e.getMessage().contains(\"服务器响应空\");\n    if (!empty || ++attempts > 2) throw e;\n    Thread.sleep(1000L * attempts);\n  }\n}","preventionTips":["Verify apiHostUrl/proxy does not strip response bodies.","Confirm upload size is within WeChat endpoint limits.","Log HTTP status/headers when this fires to localise the empty-body source."],"tags":["upload","apache-http","empty-response","network","transient"],"backgroundTag":null,"analyzedSha":"1c43293a3c2c9d7e91304b6d037fb017f680d0c6","analyzedAt":"2026-08-14T02:29:11.060Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}