{"record":{"id":"3e0de4bf289a63a8","repo":"binarywang/WxJava","slug":"error","errorCode":null,"errorMessage":"响应为空","messagePattern":"响应为空","errorType":"exception","errorClass":"WxErrorException","httpStatus":null,"severity":"error","filePath":"weixin-java-aispeech/src/main/java/me/chanjar/weixin/aispeech/api/impl/WxAispeechDialogServiceImpl.java","lineNumber":120,"sourceCode":"\n    Type type = new TypeToken<AispeechApiResponse<DialogResult>>() { } .getType();\n    AispeechApiResponse<DialogResult> result = WxGsonBuilder.create().fromJson(responseJson, type);\n    ensureSuccess(result);\n\n    DialogResult dialogResult = result.getData();\n    if (dialogResult != null && looksLikeJson(dialogResult.getAnswer())) {\n      dialogResult.setRawAnswer(WxGsonBuilder.create().fromJson(dialogResult.getAnswer(), JsonElement.class));\n    }\n    return dialogResult;\n  }\n\n  private boolean looksLikeJson(String value) {\n    return StringUtils.isNotBlank(value) && (value.startsWith(\"{\") || value.startsWith(\"[\"));\n  }\n\n  private void ensureSuccess(AispeechApiResponse<?> response) throws WxErrorException {\n    if (response == null) {\n      throw new WxErrorException(\"响应为空\");\n    }\n    if (response.getCode() == null || response.getCode() != 0) {\n      throw new WxErrorException(WxError.builder()\n        .errorCode(response.getCode() == null ? -1 : response.getCode())\n        .errorMsg(response.getMsg())\n        .build());\n    }\n  }\n}\n","sourceCodeStart":102,"sourceCodeEnd":130,"githubUrl":"https://github.com/binarywang/WxJava/blob/1c43293a3c2c9d7e91304b6d037fb017f680d0c6/weixin-java-aispeech/src/main/java/me/chanjar/weixin/aispeech/api/impl/WxAispeechDialogServiceImpl.java#L102-L130","documentation":"Thrown by `ensureSuccess` in the AI Speech dialog service when the parsed `AispeechApiResponse` is null, i.e. the HTTP body could not be deserialized into a response object at all. It is a WxErrorException. A separate branch handles non-zero `code` with the server's msg; this specific message is only the null-response case.","triggerScenarios":"Dialog API returns an empty or non-JSON body, a network/proxy returns an HTML error page, the endpoint URL is wrong (404 body), or the response model fails to deserialize so the caller receives null.","commonSituations":"Wrong `dialogApiBaseUrl`; gateway/proxy intercepting with an HTML error; region or environment mismatch; API contract change after an SDK/server version bump.","solutions":["Enable request/response logging to capture the raw body returned by the dialog endpoint.","Verify `dialogApiBaseUrl` is correct and reachable; check for proxy/gateway HTML responses.","Confirm the AI Speech service account/network allows egress to the endpoint.","If the contract changed, update the SDK or align the server response to the expected JSON."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Not applicable: cannot pre-validate a remote null response. Validate connectivity instead.\nif (StringUtils.isBlank(configStorage.getDialogApiBaseUrl())) {\n    throw new IllegalStateException(\"dialogApiBaseUrl is not configured\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    WxAispeechDialogResult r = service.dialog(...);\n} catch (WxErrorException e) {\n    if (\"响应为空\".equals(e.getMessage())) {\n        // log raw transport details; likely wrong endpoint or non-JSON body\n        log.error(\"Dialog returned empty/unparseable body from {}\", configStorage.getDialogApiBaseUrl(), e);\n    }\n    throw e;\n}","preventionTips":["Point dialogApiBaseUrl at the correct environment endpoint.","Ensure no proxy/gateway returns HTML for the API path.","Log raw response bodies during integration to catch contract drift."],"tags":["aispeech","network","deserialization","runtime"],"backgroundTag":null,"analyzedSha":"1c43293a3c2c9d7e91304b6d037fb017f680d0c6","analyzedAt":"2026-08-14T02:29:11.060Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}