apolloconfig/apollo · warning · BadRequestException
AppId not equal. AppId in path = %s, AppId in payload = %s
Error message
AppId not equal. AppId in path = %s, AppId in payload = %s
What it means
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.
Source
Thrown at apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/ClusterController.java:61
@RestController
public class ClusterController {
private final ClusterService clusterService;
private final UserInfoHolder userInfoHolder;
public ClusterController(final ClusterService clusterService,
final UserInfoHolder userInfoHolder) {
this.clusterService = clusterService;
this.userInfoHolder = userInfoHolder;
}
@PreAuthorize(value = "@unifiedPermissionValidator.hasCreateClusterPermission(#appId)")
@PostMapping(value = "apps/{appId}/envs/{env}/clusters")
@ApolloAuditLog(type = OpType.CREATE, name = "Cluster.create")
public ClusterDTO createCluster(@PathVariable String appId, @PathVariable String env,
@Valid @RequestBody ClusterDTO cluster) {
if (!Objects.equals(appId, cluster.getAppId())) {
throw new BadRequestException("AppId not equal. AppId in path = %s, AppId in payload = %s",
appId, cluster.getAppId());
}
String operator = userInfoHolder.getUser().getUserId();
cluster.setDataChangeLastModifiedBy(operator);
cluster.setDataChangeCreatedBy(operator);
return clusterService.createCluster(Env.valueOf(env), cluster, operator);
}
@PreAuthorize(value = "@unifiedPermissionValidator.isSuperAdmin()")
@DeleteMapping(value = "apps/{appId}/envs/{env}/clusters/{clusterName:.+}")
@ApolloAuditLog(type = OpType.DELETE, name = "Cluster.delete")
public ResponseEntity<Void> deleteCluster(@PathVariable String appId, @PathVariable String env,
@PathVariable String clusterName) {
clusterService.deleteCluster(Env.valueOf(env), appId, clusterName,
userInfoHolder.getUser().getUserId());
return ResponseEntity.ok().build();View on GitHub (pinned to d95fc18d11)
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.
Example fix
// before
POST /apps/sample-app/envs/DEV/clusters
body: { "appId": "sampleApp", "name": "cluster-x" }
// after
POST /apps/sample-app/envs/DEV/clusters
body: { "appId": "sample-app", "name": "cluster-x" } Defensive patterns
Strategy: validation
Validate before calling
// Assert path appId == ClusterDTO.appId before POST apps/{appId}/envs/{env}/clusters.
if (!Objects.equals(pathAppId, clusterDto.getAppId())) {
clusterDto.setAppId(pathAppId);
}
assert Objects.equals(pathAppId, clusterDto.getAppId()); Type guard
static boolean clusterMatchesPath(ClusterDTO cluster, String pathAppId) {
return cluster != null && Objects.equals(pathAppId, cluster.getAppId());
} Prevention
- 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.
When it happens
Trigger: POST /apps/{appId}/envs/{env}/clusters with a ClusterDTO whose appId field does not equal the {appId} in the URL.
Common situations: 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.
Related errors
- The App Id of path variable and request body is different
- The App Id of path variable and request body is different
- AppId not equal. AppId in path = %s, AppId in payload = %s
- Current user not found
- The app does not exist in the specified environment and clus
AI-assisted analysis of apolloconfig/apollo@d95fc18d11 (2026-08-14).
Data as JSON: /api/errors/ba52e7ff284a4aba.
Report an issue: GitHub.