{"record":{"id":"113f2e8f4b34706c","repo":"binarywang/WxJava","slug":"corpid","errorCode":null,"errorMessage":"请确保企业微信配置唯一性[{corpId}]","messagePattern":"请确保企业微信配置唯一性\\[(.+?)\\]","errorType":"validation","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"solon-plugins/wx-java-cp-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/cp_multi/configuration/services/AbstractWxCpConfiguration.java","lineNumber":64,"sourceCode":"     * <p>但同一 corpId 下不允许出现重复的 agentId（包括多个 null）。</p>\n     *\n     * 查看 {@link me.chanjar.weixin.cp.config.impl.AbstractWxCpInRedisConfigImpl#setAgentId(Integer)}\n     */\n    Collection<WxCpSingleProperties> corpList = corps.values();\n    if (corpList.size() > 1) {\n      // 先按 corpId 分组统计\n      Map<String, List<WxCpSingleProperties>> corpsMap = corpList.stream()\n        .collect(Collectors.groupingBy(WxCpSingleProperties::getCorpId));\n      Set<Map.Entry<String, List<WxCpSingleProperties>>> entries = corpsMap.entrySet();\n      for (Map.Entry<String, List<WxCpSingleProperties>> entry : entries) {\n        String corpId = entry.getKey();\n        // 校验每个企业下，agentId 是否唯一\n        boolean multi = entry.getValue().stream()\n          // 通讯录没有 agentId，使用字符串转换避免 null 与 agentId=0 冲突\n          .collect(Collectors.groupingBy(c -> Objects.toString(c.getAgentId(), \"null\"), Collectors.counting()))\n          .entrySet().stream().anyMatch(e -> e.getValue() > 1);\n        if (multi) {\n          throw new RuntimeException(\"请确保企业微信配置唯一性[\" + corpId + \"]\");\n        }\n      }\n    }\n    WxCpMultiServicesImpl services = new WxCpMultiServicesImpl();\n\n    Set<Map.Entry<String, WxCpSingleProperties>> entries = corps.entrySet();\n    for (Map.Entry<String, WxCpSingleProperties> entry : entries) {\n      String tenantId = entry.getKey();\n      WxCpSingleProperties wxCpSingleProperties = entry.getValue();\n      WxCpDefaultConfigImpl storage = this.wxCpConfigStorage(wxCpMultiProperties);\n      this.configCorp(storage, wxCpSingleProperties);\n      this.configHttp(storage, wxCpMultiProperties.getConfigStorage());\n      WxCpService wxCpService = this.wxCpService(storage, wxCpMultiProperties.getConfigStorage());\n      services.addWxCpService(tenantId, wxCpService);\n    }\n    return services;\n  }\n","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/binarywang/WxJava/blob/1c43293a3c2c9d7e91304b6d037fb017f680d0c6/solon-plugins/wx-java-cp-multi-solon-plugin/src/main/java/com/binarywang/solon/wxjava/cp_multi/configuration/services/AbstractWxCpConfiguration.java#L46-L82","documentation":"Thrown by the Solon multi-account WeChat Work (企业微信) auto-configuration. It groups configured apps by `corpId`, then within each corp requires `agentId` to be unique. Duplicate agentId under the same corp would collide on token caches keyed by corpId+agentId. It is a RuntimeException carrying the offending corpId in the message.","triggerScenarios":"Two tenant entries sharing both the same `corpId` and the same `agentId`. Note: contacts-sync apps legitimately have a null agentId; the code maps null to the string \"null\" so that two null-agentId entries under one corp are *also* treated as duplicates.","commonSituations":"Adding a second self-built app under the same enterprise but reusing the agentId; mis-pasting an agentId; configuring two contacts apps (agentId null) for one corp.","solutions":["Find the corpId named in the message and check every app under that corp.","Give each app a distinct `agentId`; for multiple contacts-type apps under one corp, you cannot — split them across separate corp configs or instances.","Re-deploy once the duplicate is resolved."],"exampleFix":"// before\nwxjava:\n  cp:\n    apps:\n      a: { corpId: ww1, agentId: 1000002 }\n      b: { corpId: ww1, agentId: 1000002 }  # duplicate -> throws 请确保企业微信配置唯一性[ww1]\n// after\n      b: { corpId: ww1, agentId: 1000005 }","handlingStrategy":"validation","validationCode":"// Validate corpId+agentId uniqueness before wiring WxCpMultiServicesImpl\nMap<String, List<WxCpSingleProperties>> byCorp = corpList.stream()\n    .collect(Collectors.groupingBy(WxCpSingleProperties::getCorpId));\nfor (Map.Entry<String, List<WxCpSingleProperties>> e : byCorp.entrySet()) {\n    Set<String> seen = new HashSet<>();\n    for (WxCpSingleProperties p : e.getValue()) {\n        String key = Objects.toString(p.getAgentId(), \"null\");\n        if (!seen.add(key)) {\n            throw new IllegalStateException(\n                \"Duplicate agentId \" + key + \" under corp \" + e.getKey());\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep a single inventory of corpId/agentId pairs and check for duplicates on deploy.","Remember contacts apps share the null-agentId slot — at most one per corp.","Name tenant keys after the agent to make collisions obvious."],"tags":["config","multi-tenant","wecom","cp","solon","startup"],"backgroundTag":null,"analyzedSha":"1c43293a3c2c9d7e91304b6d037fb017f680d0c6","analyzedAt":"2026-08-14T02:29:11.060Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}