{"record":{"id":"f7113c5272fb0857","repo":"binarywang/WxJava","slug":"x-appid","errorCode":null,"errorMessage":"X-APPID不能为空","messagePattern":"X-APPID不能为空","errorType":"validation","errorClass":"WxErrorException","httpStatus":null,"severity":"error","filePath":"weixin-java-aispeech/src/main/java/me/chanjar/weixin/aispeech/api/impl/WxAispeechServiceImpl.java","lineNumber":111,"sourceCode":"    long timestamp = System.currentTimeMillis() / 1000;\n    String nonce = randomNonce();\n    String sign = WxAispeechSignUtil.calcDialogSign(configStorage.getToken(), timestamp, nonce, body);\n    String resolvedAppid = StringUtils.defaultIfBlank(appid, configStorage.getAppid());\n\n    HttpPost request = new HttpPost(configStorage.getDialogApiBaseUrl() + path);\n    request.setHeader(\"request_id\", requestId);\n    request.setHeader(\"timestamp\", String.valueOf(timestamp));\n    request.setHeader(\"nonce\", nonce);\n    request.setHeader(\"sign\", sign);\n    request.setHeader(\"Content-Type\", ContentType.APPLICATION_JSON.getMimeType());\n    if (withOpenToken) {\n      if (StringUtils.isBlank(configStorage.getOpenAiToken())) {\n        throw new WxErrorException(\"X-OPENAI-TOKEN不能为空，请先调用getAccessToken或手动设置\");\n      }\n      request.setHeader(\"X-OPENAI-TOKEN\", configStorage.getOpenAiToken());\n    } else {\n      if (StringUtils.isBlank(resolvedAppid)) {\n        throw new WxErrorException(\"X-APPID不能为空\");\n      }\n      request.setHeader(\"X-APPID\", resolvedAppid);\n    }\n    request.setEntity(new StringEntity(body, ContentType.APPLICATION_JSON));\n    return executeRequest(request);\n  }\n\n  protected String executeKnowledgeGet(String path, Map<String, String> queryParams) throws WxErrorException {\n    try {\n      URIBuilder builder = new URIBuilder(configStorage.getKnowledgeApiBaseUrl() + path);\n      if (queryParams != null) {\n        for (Map.Entry<String, String> entry : queryParams.entrySet()) {\n          if (entry.getValue() != null) {\n            builder.addParameter(entry.getKey(), entry.getValue());\n          }\n        }\n      }\n      HttpGet request = new HttpGet(builder.build());","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/binarywang/WxJava/blob/1c43293a3c2c9d7e91304b6d037fb017f680d0c6/weixin-java-aispeech/src/main/java/me/chanjar/weixin/aispeech/api/impl/WxAispeechServiceImpl.java#L93-L129","documentation":"Thrown by `executeDialogPost` when a dialog call is made with `withOpenToken=false` and neither the per-call `appid` argument nor `configStorage.appid` is set. The resolved appid (`defaultIfBlank(appid, configStorage.appid)`) is required for the `X-APPID` header. It is a WxErrorException.","triggerScenarios":"Calling a non-OpenAI-token dialog path while the global appid was never configured and no appid was passed to the method.","commonSituations":"Config storage created without setting appid; relying on a per-call appid but passing null; partial config after migrating setup code.","solutions":["Set appid on the config storage at init: `configStorage.setAppid(...)`.","Or pass a non-blank appid to the dialog method call.","Validate configuration completeness before issuing requests."],"exampleFix":"// before\nString r = service.executeDialogPost(path, body, false, null);  // throws\n// after\nconfigStorage.setAppid(\"your-appid\");\nString r = service.executeDialogPost(path, body, false, null);","handlingStrategy":"validation","validationCode":"// Ensure an appid is resolvable for non-OpenAI-token dialog calls\nString resolvedAppid = StringUtils.defaultIfBlank(appid, configStorage.getAppid());\nif (!withOpenToken && StringUtils.isBlank(resolvedAppid)) {\n    throw new IllegalStateException(\"No appid available for X-APPID header\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always set appid on the config storage at init.","Pass an explicit appid when tenants differ per call.","Add a config-completeness assertion at startup."],"tags":["aispeech","config","runtime"],"backgroundTag":null,"analyzedSha":"1c43293a3c2c9d7e91304b6d037fb017f680d0c6","analyzedAt":"2026-08-14T02:29:11.060Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}