{"record":{"id":"bf2993faafdc4249","repo":"apolloconfig/apollo","slug":"delete-namespace-permission-is-required","errorCode":null,"errorMessage":"Delete namespace permission is required","messagePattern":"Delete namespace permission is required","errorType":"exception","errorClass":"AccessDeniedException","httpStatus":403,"severity":"error","filePath":"apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/v1/controller/NamespaceController.java","lineNumber":396,"sourceCode":"          namespace.getClusterName(), namespace.getAppNamespaceName());\n    }\n  }\n\n  private void requireCreateNamespacePermissionForUserToken(String appId, String env,\n      String clusterName, String namespaceName) {\n    if (UserIdentityConstants.USER_TOKEN.equals(UserIdentityContextHolder.getAuthType())\n        && !unifiedPermissionValidator.hasCreateNamespacePermission(appId, env, clusterName,\n            namespaceName)) {\n      throw new AccessDeniedException(\"Create namespace permission is required\");\n    }\n  }\n\n  private void requireDeleteNamespacePermissionForUserToken(String appId, String env,\n      String clusterName, String namespaceName) {\n    if (UserIdentityConstants.USER_TOKEN.equals(UserIdentityContextHolder.getAuthType())\n        && !unifiedPermissionValidator.hasDeleteNamespacePermission(appId, env, clusterName,\n            namespaceName)) {\n      throw new AccessDeniedException(\"Delete namespace permission is required\");\n    }\n  }\n\n  private String resolveOperator(String queryOperator, String payloadOperator) {\n    String authType = UserIdentityContextHolder.getAuthType();\n    if (UserIdentityConstants.USER.equals(authType)\n        || UserIdentityConstants.USER_TOKEN.equals(authType)) {\n      UserInfo loginUser = userInfoHolder.getUser();\n      if (loginUser == null || StringUtils.isBlank(loginUser.getUserId())) {\n        throw new BadRequestException(\"Current user not found\");\n      }\n      return loginUser.getUserId();\n    }\n\n    if (UserIdentityConstants.CONSUMER.equals(authType)) {\n      String operator = StringUtils.isBlank(queryOperator) ? payloadOperator : queryOperator;\n      RequestPrecondition.checkArguments(!StringUtils.isContainEmpty(operator),\n          \"operator should not be null or empty\");","sourceCodeStart":378,"sourceCodeEnd":414,"githubUrl":"https://github.com/apolloconfig/apollo/blob/d95fc18d112589efc09ddcbe1507047584d55251/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/v1/controller/NamespaceController.java#L378-L414","documentation":"HTTP 403 (AccessDeniedException). Thrown by NamespaceController.requireDeleteNamespacePermissionForUserToken: auth type USER_TOKEN and UnifiedPermissionValidator.hasDeleteNamespacePermission(appId,env,cluster,namespace) is false. The user-token lacks the delete-namespace permission needed to remove a namespace.","triggerScenarios":"DELETE namespace on NamespaceController using a user-token whose owner lacks DeleteNamespace role on the target appId/env/cluster/namespace.","commonSituations":"User-token has modify/create but not delete rights (delete is typically the most restricted); namespace deletion attempted by a CI token scoped to config edits; role narrowed after automation was written.","solutions":["Grant the user-token owner DeleteNamespace permission on the target appId/env/cluster/namespace.","Use a portal USER that holds delete-namespace rights or a CONSUMER token scoped for deletion.","Confirm deletion is intended; namespaces under released configs are protected.","Pre-check hasDeleteNamespacePermission before issuing DELETE."],"exampleFix":"// before: user-token owner lacks DeleteNamespace\nclient.withUserToken(token).deleteNamespace(\"appX\", env, cluster, ns); // 403\n\n// after: grant delete-namespace then retry\nadmin.grantDeleteNamespace(\"appX\", env, cluster, ns, token.getOwnerId());\nclient.withUserToken(token).deleteNamespace(\"appX\", env, cluster, ns);","handlingStrategy":"validation","validationCode":"// For USER_TOKEN namespace delete: confirm DeleteNamespace permission.\nif (!hasDeleteNamespace(tokenOwner, appId, env, cluster, ns)) {\n  // grant DeleteNamespace or skip; do not call deleteNamespace\n}","typeGuard":"null","tryCatchPattern":"try {\n  client.withUserToken(token).deleteNamespace(appId, env, cluster, ns);\n} catch (HttpServerErrorException.Forbidden e) {\n  // Delete namespace permission is required -> grant and retry\n}","preventionTips":["Grant DeleteNamespace only to dedicated cleanup automation.","Pre-check delete permission before issuing DELETE.","Remember namespaces under released configs are additionally protected."],"tags":["apollo-portal","openapi","permission","access-denied","namespace","delete","user-token"],"backgroundTag":null,"analyzedSha":"d95fc18d112589efc09ddcbe1507047584d55251","analyzedAt":"2026-08-14T04:00:05.477Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}