{"record":{"id":"87ac2ce37f347002","repo":"binarywang/WxJava","slug":"appid-87ac2c","errorCode":null,"errorMessage":"请确保微信公众号配置 appId 的唯一性","messagePattern":"请确保微信公众号配置 appId 的唯一性","errorType":"validation","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"solon-plugins/wx-java-miniapp-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/miniapp/configuration/services/AbstractWxMaConfiguration.java","lineNumber":53,"sourceCode":"    Map<String, WxMaSingleProperties> appsMap = wxMaMultiProperties.getApps();\n    if (appsMap == null || appsMap.isEmpty()) {\n      log.warn(\"微信公众号应用参数未配置，通过 WxMaMultiServices#getWxMaService(\\\"tenantId\\\")获取实例将返回空\");\n      return new WxMaMultiServicesImpl();\n    }\n    /**\n     * 校验 appId 是否唯一，避免使用 redis 缓存 token、ticket 时错乱。\n     *\n     * 查看 {@link cn.binarywang.wx.miniapp.config.impl.WxMaRedisConfigImpl#setAppId(String)}\n     */\n    Collection<WxMaSingleProperties> apps = appsMap.values();\n    if (apps.size() > 1) {\n      // 校验 appId 是否唯一\n      boolean multi = apps.stream()\n        // 没有 appId，如果不判断是否为空，这里会报 NPE 异常\n        .collect(Collectors.groupingBy(c -> c.getAppId() == null ? 0 : c.getAppId(), Collectors.counting()))\n        .entrySet().stream().anyMatch(e -> e.getValue() > 1);\n      if (multi) {\n        throw new RuntimeException(\"请确保微信公众号配置 appId 的唯一性\");\n      }\n    }\n    WxMaMultiServicesImpl services = new WxMaMultiServicesImpl();\n\n    Set<Map.Entry<String, WxMaSingleProperties>> entries = appsMap.entrySet();\n    for (Map.Entry<String, WxMaSingleProperties> entry : entries) {\n      String tenantId = entry.getKey();\n      WxMaSingleProperties wxMaSingleProperties = entry.getValue();\n      WxMaDefaultConfigImpl storage = this.wxMaConfigStorage(wxMaMultiProperties);\n      this.configApp(storage, wxMaSingleProperties);\n      this.configHttp(storage, wxMaMultiProperties.getConfigStorage());\n      WxMaService wxMaService = this.wxMaService(storage, wxMaMultiProperties);\n      services.addWxMaService(tenantId, wxMaService);\n    }\n    return services;\n  }\n\n  /**","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/binarywang/WxJava/blob/1c43293a3c2c9d7e91304b6d037fb017f680d0c6/solon-plugins/wx-java-miniapp-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/miniapp/configuration/services/AbstractWxMaConfiguration.java#L35-L71","documentation":"Thrown by the Solon multi-account MiniProgram (小程序) auto-configuration when two tenants resolve to the same appId, to prevent Redis token/ticket cache collisions. NOTE: the message string literally says \"微信公众号\" (Official Account) even though this is the miniapp module — a copy-paste bug in the message text; treat it as the miniapp appId-uniqueness error.","triggerScenarios":"Two entries under `wxjava.miniapp.apps.*` with the same `appId`, or two entries both with null appId (null is collapsed to key `0`).","commonSituations":"Same appId reused for two mini-program tenant blocks; appId left blank on multiple entries; being misled by the wrong product name in the message and looking in the MP config instead of the miniapp config.","solutions":["Recognize this is the MINIAPP config despite the message wording; open `wxjava.mini.apps`.","Give each tenant a distinct mini-program `appId`.","Fill in any blank appIds; restart."],"exampleFix":"// before\nwxjava:\n  miniapp:\n    apps:\n      t1: { appId: wxmini001 }\n      t2: { appId: wxmini001 }  # throws (message wrongly says 公众号)\n// after\n      t2: { appId: wxmini002 }","handlingStrategy":"validation","validationCode":"// Miniapp: validate appId uniqueness (note: message text wrongly says 公众号)\nSet<String> seen = new HashSet<>();\nfor (WxMaSingleProperties p : appsMap.values()) {\n    String id = p.getAppId();\n    if (id == null || !seen.add(id)) {\n        throw new IllegalStateException(\"Miniapp appId missing or duplicated: \" + id);\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Do not be misled by the wrong product name in the message — this is the miniapp config.","Fill every appId; never rely on a null default.","Diff tenant blocks in code review to catch copy-paste."],"tags":["config","multi-tenant","miniapp","solon","startup","message-bug"],"backgroundTag":null,"analyzedSha":"1c43293a3c2c9d7e91304b6d037fb017f680d0c6","analyzedAt":"2026-08-14T02:29:11.060Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}