{"record":{"id":"08c3aa68d80dc113","repo":"binarywang/WxJava","slug":"appid-08c3aa","errorCode":null,"errorMessage":"请确保微信小程序配置 appId 的唯一性","messagePattern":"请确保微信小程序配置 appId 的唯一性","errorType":"validation","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"spring-boot-starters/wx-java-miniapp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/miniapp/configuration/services/AbstractWxMaConfiguration.java","lineNumber":56,"sourceCode":"    if (appsMap == null || appsMap.isEmpty()) {\n      log.warn(\"微信小程序应用参数未配置，通过 WxMaMultiServices#getWxMaService(\\\"tenantId\\\")获取实例将返回空\");\n      return new WxMaMultiServicesImpl();\n    }\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\n    // 根据配置选择多租户模式\n    WxMaMultiProperties.MultiTenantMode mode = wxMaMultiProperties.getConfigStorage().getMultiTenantMode();\n    if (mode == WxMaMultiProperties.MultiTenantMode.SHARED) {\n      return createSharedMultiServices(appsMap, wxMaMultiProperties);\n    } else {\n      return createIsolatedMultiServices(appsMap, wxMaMultiProperties);\n    }\n  }\n\n  /**\n   * 创建隔离模式的多租户服务（每个租户独立 WxMaService 实例）\n   */\n  private WxMaMultiServices createIsolatedMultiServices(\n    Map<String, WxMaSingleProperties> appsMap,\n    WxMaMultiProperties wxMaMultiProperties) {","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/binarywang/WxJava/blob/1c43293a3c2c9d7e91304b6d037fb017f680d0c6/spring-boot-starters/wx-java-miniapp-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/miniapp/configuration/services/AbstractWxMaConfiguration.java#L38-L74","documentation":"Thrown by the Spring Boot multi-account MiniProgram (小程序) starter when two tenants share the same appId, preventing Redis token/ticket cache key collisions (see WxMaRedisConfigImpl#setAppId). Unlike the Solon sibling, this message correctly says \"微信小程序\". After the check passes, the starter branches into SHARED vs ISOLATED multi-tenant mode.","triggerScenarios":"Two entries under `wx.miniapp.apps` with the same `appId`; two entries both with null appId (collapsed to key `0`).","commonSituations":"Reusing one mini-program appId on multiple tenant keys; blank appIds after partial config migration.","solutions":["Enumerate `wx.miniapp.apps.*.appId` and ensure all are distinct and non-blank.","Restart once deduplicated.","Then verify `multiTenantMode` (SHARED/ISOLATED) matches your cache isolation intent."],"exampleFix":"# before\nwx.miniapp.apps:\n  t1: { appId: wxmini001 }\n  t2: { appId: wxmini001 }\n# after\nwx.miniapp.apps:\n  t1: { appId: wxmini001 }\n  t2: { appId: wxmini003 }","handlingStrategy":"validation","validationCode":"// Spring Boot Miniapp multi: pre-flight appId uniqueness\nSet<String> seen = new HashSet<>();\nfor (WxMaSingleProperties p : appsMap.values()) {\n    if (p.getAppId() == null || !seen.add(p.getAppId())) {\n        throw new IllegalStateException(\"Duplicate/null miniapp appId\");\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Dedicate one mini-program appId per tenant.","Pick SHARED vs ISOLATED multiTenantMode deliberately to match cache isolation.","Validate config in a test that boots the autoconfiguration."],"tags":["config","multi-tenant","miniapp","spring-boot","startup"],"backgroundTag":null,"analyzedSha":"1c43293a3c2c9d7e91304b6d037fb017f680d0c6","analyzedAt":"2026-08-14T02:29:11.060Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}