{"record":{"id":"ddd609b25ba7034b","repo":"binarywang/WxJava","slug":"secretkey","errorCode":null,"errorMessage":"知识助理请求需要配置secretKey","messagePattern":"知识助理请求需要配置secretKey","errorType":"validation","errorClass":"WxErrorException","httpStatus":null,"severity":"error","filePath":"weixin-java-aispeech/src/main/java/me/chanjar/weixin/aispeech/api/impl/WxAispeechServiceImpl.java","lineNumber":187,"sourceCode":"    if (entity.getContentType() != null) {\n      request.setHeader(\"Content-Type\", entity.getContentType());\n    }\n    enrichKnowledgeHeaders(request, \"\");\n    return executeRequest(request);\n  }\n\n  protected String executeKnowledgeDelete(String path) throws WxErrorException {\n    HttpUriRequestBase request = new HttpUriRequestBase(\"DELETE\", URI.create(configStorage.getKnowledgeApiBaseUrl() + path));\n    enrichKnowledgeHeaders(request, \"\");\n    return executeRequest(request);\n  }\n\n  private void enrichKnowledgeHeaders(HttpUriRequestBase request, String body) throws WxErrorException {\n    if (StringUtils.isBlank(configStorage.getAppid())) {\n      throw new WxErrorException(\"知识助理请求需要配置appid\");\n    }\n    if (StringUtils.isBlank(configStorage.getSecretKey())) {\n      throw new WxErrorException(\"知识助理请求需要配置secretKey\");\n    }\n\n    String requestId = UUID.randomUUID().toString();\n    long timestamp = System.currentTimeMillis() / 1000;\n    String nonce = randomNonce();\n    String signature = WxAispeechSignUtil.calcKnowledgeSignature(configStorage.getSecretKey(), timestamp, nonce,\n      requestId, body);\n\n    request.setHeader(\"X-APPID\", configStorage.getAppid());\n    request.setHeader(\"X-Request-ID\", requestId);\n    request.setHeader(\"X-Timestamp\", String.valueOf(timestamp));\n    request.setHeader(\"X-Nonce\", nonce);\n    request.setHeader(\"X-Signature\", signature);\n    if (!request.containsHeader(\"Content-Type\")) {\n      request.setHeader(\"Content-Type\", ContentType.APPLICATION_JSON.getMimeType());\n    }\n  }\n","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/binarywang/WxJava/blob/1c43293a3c2c9d7e91304b6d037fb017f680d0c6/weixin-java-aispeech/src/main/java/me/chanjar/weixin/aispeech/api/impl/WxAispeechServiceImpl.java#L169-L205","documentation":"Thrown by `enrichKnowledgeHeaders` immediately after the appid check when `configStorage.secretKey` is blank. The secretKey is used to compute the HMAC signature for Knowledge-assistant requests; without it the `X-Signature` cannot be produced. It is a WxErrorException.","triggerScenarios":"Any knowledge-assistant call when appid is set but secretKey is missing/blank.","commonSituations":"Secret omitted from config; secret env var not exported; secret rotated server-side but not updated in the client config.","solutions":["Set secretKey on the config storage: `configStorage.setSecretKey(...)`.","Ensure the env var supplying the secret is present in the runtime environment.","Restart/refresh after rotation."],"exampleFix":"// before\nconfigStorage.setAppid(\"your-appid\");\nservice.executeKnowledgePost(\"/knowledge\", body);  // throws\n// after\nconfigStorage.setAppid(\"your-appid\");\nconfigStorage.setSecretKey(\"${AISPEECH_SECRET}\");\nservice.executeKnowledgePost(\"/knowledge\", body);","handlingStrategy":"validation","validationCode":"// Guard knowledge calls: require secretKey\nif (StringUtils.isBlank(configStorage.getSecretKey())) {\n    throw new IllegalStateException(\"Knowledge API requires secretKey to be configured\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Supply secretKey via a secrets manager / env var.","Fail fast at startup if secretKey is blank.","Rotate secretKey and update client config atomically."],"tags":["aispeech","knowledge","config","secret","runtime"],"backgroundTag":null,"analyzedSha":"1c43293a3c2c9d7e91304b6d037fb017f680d0c6","analyzedAt":"2026-08-14T02:29:11.060Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}