apolloconfig/apollo · error · 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
Thrown by ClusterController.createCluster when the appId in the URL path does not match the appId field inside the OpenClusterDTO JSON body. Apollo enforces referential integrity between the path parameter and the payload to prevent a caller from accidentally creating a cluster under the wrong app. Maps to HTTP 400 BadRequestException.
Source
Thrown at apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/v1/controller/ClusterController.java:69
this.clusterOpenApiService = clusterOpenApiService;
this.userInfoHolder = userInfoHolder;
this.unifiedPermissionValidator = unifiedPermissionValidator;
}
@Override
public ResponseEntity<OpenClusterDTO> getCluster(String appId, String clusterName, String env) {
requireReadApplicationPermissionForUserToken(appId);
return ResponseEntity.ok(this.clusterOpenApiService.getCluster(appId, env, clusterName));
}
@PreAuthorize(value = "@unifiedPermissionValidator.hasCreateClusterPermission(#appId)")
@ApolloAuditLog(type = OpType.CREATE, name = "Cluster.create")
@Override
public ResponseEntity<OpenClusterDTO> createCluster(String appId, String env,
OpenClusterDTO 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 clusterName = cluster.getName();
requireCreateClusterPermissionForUserToken(appId, env, clusterName);
String operator = resolveOperator(cluster.getDataChangeCreatedBy());
cluster.setDataChangeLastModifiedBy(operator);
cluster.setDataChangeCreatedBy(operator);
RequestPrecondition.checkArguments(!StringUtils.isContainEmpty(clusterName, operator),
"name and dataChangeCreatedBy should not be null or empty");
if (!InputValidator.isValidClusterNamespace(clusterName)) {
throw BadRequestException
.invalidClusterNameFormat(InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE);
}
return ResponseEntity.ok(this.clusterOpenApiService.createCluster(env, cluster, operator));View on GitHub (pinned to d95fc18d11)
Solutions
- Make the appId in the JSON body identical to the appId in the URL path — set cluster.setAppId(appId) before sending.
- Use a single source variable for appId in client code to populate both the path and the body.
- Add a client-side assertion: Objects.equals(pathAppId, body.getAppId()) before the HTTP call.
Example fix
// before — path and body appId can diverge
String urlAppId = "someApp";
OpenClusterDTO cluster = new OpenClusterDTO();
cluster.setAppId(config.getString("cluster.appId")); // different source!
cluster.setName("prod-cluster");
client.post("/openapi/v1/envs/PROD/apps/" + urlAppId + "/clusters", cluster);
// after — single source of truth for appId
String appId = "someApp";
OpenClusterDTO cluster = new OpenClusterDTO();
cluster.setAppId(appId);
cluster.setName("prod-cluster");
client.post("/openapi/v1/envs/PROD/apps/" + appId + "/clusters", cluster); Defensive patterns
Strategy: validation
Validate before calling
// Validate path appId matches body appId before the HTTP call
if (!Objects.equals(pathAppId, clusterBody.getAppId())) {
throw new IllegalArgumentException(
String.format("AppId mismatch: path=%s, body=%s", pathAppId, clusterBody.getAppId()));
}
// Or simply sync them:
clusterBody.setAppId(pathAppId); Prevention
- Use a single variable for appId and derive both the URL path and the body field from it.
- Add a pre-send assertion in API client wrappers that path and body appIds match.
- In integration tests, parametrize both path and body appId from the same source.
When it happens
Trigger: POST /openapi/v1/envs/{env}/apps/appA/clusters where the JSON body contains {"appId":"appB","name":"myCluster"}. The Objects.equals(appId, cluster.getAppId()) guard catches the mismatch.
Common situations: Copy-pasting a request body template from another app without updating the appId field. Automation scripts that construct the path from one variable and the body from another, where the two variables diverge due to a bug.
Related errors
- Current user not found
- releaseIds should not be empty
- releaseIds should be comma separated numbers
- Comment length should not exceed %s characters
- Current user not found
AI-assisted analysis of apolloconfig/apollo@d95fc18d11 (2026-08-14).
Data as JSON: /api/errors/092e7b3d5ca27abe.
Report an issue: GitHub.