apolloconfig/apollo · warning · AccessDeniedException

You don't have the permission to modify namespace: %s

Error message

You don't have the permission to modify namespace: %s

What it means

AccessDeniedException (HTTP 403) from ItemController namespace sync. The handler iterates syncToNamespaces, checks hasModifyNamespacePermission for each target, and on the first namespace the user lacks permission to modify it records that NamespaceIdentifier and breaks; if not all targets are permitted it throws, formatting the offending identifier via NamespaceIdentifier.toString() (appId/env/cluster/namespace).

Source

Thrown at apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/ItemController.java:228

    NamespaceIdentifier noPermissionNamespace = null;
    // check if user has every namespace's ModifyNamespace permission
    boolean hasPermission = true;
    for (NamespaceIdentifier namespaceIdentifier : model.getSyncToNamespaces()) {
      // once user has not one of the namespace's ModifyNamespace permission, then break the loop
      hasPermission = unifiedPermissionValidator.hasModifyNamespacePermission(
          namespaceIdentifier.getAppId(), namespaceIdentifier.getEnv().getName(),
          namespaceIdentifier.getClusterName(), namespaceIdentifier.getNamespaceName());
      if (!hasPermission) {
        noPermissionNamespace = namespaceIdentifier;
        break;
      }
    }
    if (hasPermission) {
      configService.syncItems(model.getSyncToNamespaces(), model.getSyncItems(),
          userInfoHolder.getUser().getUserId());
      return ResponseEntity.status(HttpStatus.OK).build();
    }
    throw new AccessDeniedException(String
        .format("You don't have the permission to modify namespace: %s", noPermissionNamespace));
  }

  @PreAuthorize(
      value = "@unifiedPermissionValidator.hasModifyNamespacePermission(#appId, #env, #clusterName, #namespaceName)")
  @PostMapping(
      value = "/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/syntax-check",
      consumes = {"application/json"})
  public ResponseEntity<Void> syntaxCheckText(@PathVariable String appId, @PathVariable String env,
      @PathVariable String clusterName, @PathVariable String namespaceName,
      @RequestBody NamespaceTextModel model) {

    doSyntaxCheck(model);

    return ResponseEntity.ok().build();
  }

  @PreAuthorize(

View on GitHub (pinned to d95fc18d11)

Solutions

  1. Request ModifyNamespace permission on the namespace named in the error (appId/env/cluster/namespace).
  2. Remove the unauthorized target from syncToNamespaces and sync to permitted namespaces only.
  3. Have an app admin grant the role or perform the sync on your behalf.
  4. Check each target's permission before submitting (see validationCode) when a permission API is available.

Example fix

// before
syncToNamespaces = [prod-allowed, locked-down-env]   // 403 on locked-down-env

// after
syncToNamespaces = [prod-allowed]   // sync only permitted targets
Defensive patterns

Strategy: try-catch

Validate before calling

// Best-effort pre-check: only keep targets the user can modify (requires a permission lookup API).
List<NamespaceIdentifier> permitted = new ArrayList<>();
for (NamespaceIdentifier t : model.getSyncToNamespaces()) {
  if (permissionApi.canModifyNamespace(t.getAppId(), t.getEnv().getName(),
                                       t.getClusterName(), t.getNamespaceName())) {
    permitted.add(t);
  }
}
if (permitted.size() != model.getSyncToNamespaces().size()) {
  // show user which targets they cannot modify, or sync only permitted ones
}
model.setSyncToNamespaces(permitted);

Try / catch

// Namespace sync can 403 per-target.
try {
  portal.syncItems(model);
} catch (HttpClientErrorException.Forbidden e) {
  // body contains the offending NamespaceIdentifier (appId/env/cluster/namespace)
  reportMissingPermission(extractNamespaceIdentifier(e.getResponseBodyAsString()));
}

Prevention

When it happens

Trigger: POST the sync-items flow where model.syncToNamespaces contains at least one namespace the current user cannot Modify (missing ModifyNamespace role on that appId/env/cluster/namespace).

Common situations: User has modify rights on the source namespace but not on one target env/cluster; cross-env sync to a locked-down environment; role was revoked between opening the page and submitting.

Related errors


AI-assisted analysis of apolloconfig/apollo@d95fc18d11 (2026-08-14). Data as JSON: /api/errors/191e769544fdb6c7. Report an issue: GitHub.