{"record":{"id":"e5bc9ae8dffc8c71","repo":"binarywang/WxJava","slug":"url-s-param-s-e5bc9a","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/CommonUploadRequestExecutorJoddHttpImpl.java","lineNumber":54,"sourceCode":"    HttpRequest request = HttpRequest.post(uri);\n    if (requestHttp.getRequestHttpProxy() != null) {\n      requestHttp.getRequestHttpClient().useProxy(requestHttp.getRequestHttpProxy());\n    }\n    request.withConnectionProvider(requestHttp.getRequestHttpClient());\n    request.form(param.getName(), new CommonUploadParamToUploadableAdapter(param.getData()));\n\n    // 添加额外的表单字段\n    if (param.getFormFields() != null && !param.getFormFields().isEmpty()) {\n      for (java.util.Map.Entry<String, String> entry : param.getFormFields().entrySet()) {\n        request.form(entry.getKey(), entry.getValue());\n      }\n    }\n\n    HttpResponse response = request.send();\n    response.charset(StandardCharsets.UTF_8.name());\n    String responseContent = response.bodyText();\n    if (responseContent.isEmpty()) {\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   * 通用上传参数 到 Uploadable 的适配器\n   */\n  @Getter\n  @AllArgsConstructor\n  public static class CommonUploadParamToUploadableAdapter implements Uploadable<CommonUploadData> {\n\n    private CommonUploadData content;\n\n    @SneakyThrows","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/binarywang/WxJava/blob/1c43293a3c2c9d7e91304b6d037fb017f680d0c6/weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutorJoddHttpImpl.java#L36-L72","documentation":"The Jodd HTTP upload executor throws when response.bodyText() is empty after the multipart POST. Same fast-fail contract as the Apache variants: an empty body cannot be turned into a WxError, so it throws with the URL and param. Note Jodd uses responseContent.isEmpty() (not StringUtils.isEmpty), so only truly empty strings trigger this.","triggerScenarios":"The Jodd backend receives HTTP 200 with an empty body during upload; a proxy/gateway strips the response; the endpoint returns an empty page.","commonSituations":"Jodd-configured service behind a WAF/proxy that returns empty; transient infra issues; incorrect endpoint returning an empty body.","solutions":["Retry once — empty responses are usually transient.","Verify apiHostUrl and any proxy in front of the Jodd client.","Switch to Apache HttpClient (4.x/5.x) if Jodd upload reliability is poor in your environment.","Log HTTP status/headers to identify the layer returning empty."],"exampleFix":"// before\nString r = service.upload(param);\n\n// after\ntry {\n  return service.upload(param);\n} catch (WxErrorException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"服务器响应空\")) {\n    return service.upload(param);\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":["If Jodd upload reliability is poor, switch the service to Apache HttpClient.","Verify apiHostUrl and any proxy in front of the Jodd client.","Confirm upload size is within endpoint limits."],"tags":["upload","jodd","empty-response","network","transient"],"backgroundTag":null,"analyzedSha":"1c43293a3c2c9d7e91304b6d037fb017f680d0c6","analyzedAt":"2026-08-14T02:29:11.060Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}