{"record":{"id":"ba52e7ff284a4aba","repo":"apolloconfig/apollo","slug":"appid-not-equal-appid-in-path-s-appid-in-payl-ba52e7","errorCode":null,"errorMessage":"AppId not equal. AppId in path = %s, AppId in payload = %s","messagePattern":"AppId not equal\\. AppId in path = (.+?), AppId in payload = (.+?)","errorType":"validation","errorClass":"BadRequestException","httpStatus":400,"severity":"warning","filePath":"apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/ClusterController.java","lineNumber":61,"sourceCode":"@RestController\npublic class ClusterController {\n\n  private final ClusterService clusterService;\n  private final UserInfoHolder userInfoHolder;\n\n  public ClusterController(final ClusterService clusterService,\n      final UserInfoHolder userInfoHolder) {\n    this.clusterService = clusterService;\n    this.userInfoHolder = userInfoHolder;\n  }\n\n  @PreAuthorize(value = \"@unifiedPermissionValidator.hasCreateClusterPermission(#appId)\")\n  @PostMapping(value = \"apps/{appId}/envs/{env}/clusters\")\n  @ApolloAuditLog(type = OpType.CREATE, name = \"Cluster.create\")\n  public ClusterDTO createCluster(@PathVariable String appId, @PathVariable String env,\n      @Valid @RequestBody ClusterDTO cluster) {\n    if (!Objects.equals(appId, cluster.getAppId())) {\n      throw new BadRequestException(\"AppId not equal. AppId in path = %s, AppId in payload = %s\",\n          appId, cluster.getAppId());\n    }\n\n    String operator = userInfoHolder.getUser().getUserId();\n    cluster.setDataChangeLastModifiedBy(operator);\n    cluster.setDataChangeCreatedBy(operator);\n\n    return clusterService.createCluster(Env.valueOf(env), cluster, operator);\n  }\n\n  @PreAuthorize(value = \"@unifiedPermissionValidator.isSuperAdmin()\")\n  @DeleteMapping(value = \"apps/{appId}/envs/{env}/clusters/{clusterName:.+}\")\n  @ApolloAuditLog(type = OpType.DELETE, name = \"Cluster.delete\")\n  public ResponseEntity<Void> deleteCluster(@PathVariable String appId, @PathVariable String env,\n      @PathVariable String clusterName) {\n    clusterService.deleteCluster(Env.valueOf(env), appId, clusterName,\n        userInfoHolder.getUser().getUserId());\n    return ResponseEntity.ok().build();","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/apolloconfig/apollo/blob/d95fc18d112589efc09ddcbe1507047584d55251/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/ClusterController.java#L43-L79","documentation":"BadRequestException (HTTP 400) from ClusterController.createCluster (POST apps/{appId}/envs/{env}/clusters). It asserts the path appId equals cluster.getAppId() from the ClusterDTO body; the %s/%s placeholders are filled by Guava lenientFormat with appId then cluster.getAppId(). Reaching the service with mismatched ids would create a cluster under the wrong app, so it is blocked up front.","triggerScenarios":"POST /apps/{appId}/envs/{env}/clusters with a ClusterDTO whose appId field does not equal the {appId} in the URL.","commonSituations":"Reusing a cluster template body across apps without updating appId; UI pre-filling the body from a different cluster; trailing whitespace or case differences in the appId.","solutions":["Set cluster.setAppId(appId) using the exact path value before submitting.","If cloning a cluster from another app, copy only clusterName/config and reset appId.","Assert path-vs-body appId equality in the client (see validationCode).","Log both values on failure to catch subtle normalization differences."],"exampleFix":"// before\nPOST /apps/sample-app/envs/DEV/clusters\nbody: { \"appId\": \"sampleApp\", \"name\": \"cluster-x\" }\n\n// after\nPOST /apps/sample-app/envs/DEV/clusters\nbody: { \"appId\": \"sample-app\", \"name\": \"cluster-x\" }","handlingStrategy":"validation","validationCode":"// Assert path appId == ClusterDTO.appId before POST apps/{appId}/envs/{env}/clusters.\nif (!Objects.equals(pathAppId, clusterDto.getAppId())) {\n  clusterDto.setAppId(pathAppId);\n}\nassert Objects.equals(pathAppId, clusterDto.getAppId());","typeGuard":"static boolean clusterMatchesPath(ClusterDTO cluster, String pathAppId) {\n  return cluster != null && Objects.equals(pathAppId, cluster.getAppId());\n}","tryCatchPattern":null,"preventionTips":["Derive body.appId from the URL path variable, never from a template.","When cloning a cluster, reset appId explicitly.","Trim and compare appIds in client logs to catch normalization issues.","Add a client-side type guard before submit."],"tags":["cluster","validation","rest","id-mismatch","bad-request"],"backgroundTag":null,"analyzedSha":"d95fc18d112589efc09ddcbe1507047584d55251","analyzedAt":"2026-08-14T04:00:05.477Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}