{"record":{"id":"7ed4d52e5d544022","repo":"apolloconfig/apollo","slug":"create-namespace-permission-is-required","errorCode":null,"errorMessage":"Create namespace permission is required","messagePattern":"Create 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":387,"sourceCode":"    if (!UserIdentityConstants.USER_TOKEN.equals(UserIdentityContextHolder.getAuthType())\n        || CollectionUtils.isEmpty(namespaces)) {\n      return;\n    }\n    for (OpenCreateNamespaceDTO namespace : namespaces) {\n      if (namespace == null || StringUtils.isBlank(namespace.getAppId())) {\n        continue;\n      }\n      requireCreateNamespacePermissionForUserToken(namespace.getAppId(), namespace.getEnv(),\n          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())) {","sourceCodeStart":369,"sourceCodeEnd":405,"githubUrl":"https://github.com/apolloconfig/apollo/blob/d95fc18d112589efc09ddcbe1507047584d55251/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/v1/controller/NamespaceController.java#L369-L405","documentation":"HTTP 403 (AccessDeniedException). Thrown by NamespaceController.requireCreateNamespacePermissionForUserToken: auth type USER_TOKEN and UnifiedPermissionValidator.hasCreateNamespacePermission(appId,env,cluster,namespace) is false. The user-token lacks the create-namespace permission required to add a namespace under the app/cluster. This gate runs for every namespace in a batch create and on single creates.","triggerScenarios":"POST create namespace(s) on NamespaceController using a user-token whose owner lacks CreateNamespace role on the target app/env/cluster (or the specific app-namespace name). Fires per-entry in batch creation.","commonSituations":"User-token provisioned with modify but not create-namespace rights; creating a private/link namespace that requires an additional grant; batch create where one entry targets an app the owner cannot create in.","solutions":["Grant the user-token owner CreateNamespace permission on the target appId/env/cluster (and app-namespace if required).","Remove the unauthorized entry from the batch and retry the rest.","Use a portal USER with create-namespace rights or a CONSUMER token scoped for namespace creation.","Pre-check hasCreateNamespacePermission per entry before submitting the batch."],"exampleFix":"// before: user-token owner lacks CreateNamespace on appX\nclient.withUserToken(token).createNamespace(\"appX\", env, cluster, dto); // 403\n\n// after: grant create-namespace then retry\nadmin.grantCreateNamespace(\"appX\", env, cluster, token.getOwnerId());\nclient.withUserToken(token).createNamespace(\"appX\", env, cluster, dto);","handlingStrategy":"validation","validationCode":"// For USER_TOKEN namespace create: confirm CreateNamespace permission per target.\nfor (OpenCreateNamespaceDTO n : namespaces) {\n  if (!hasCreateNamespace(tokenOwner, n.getAppId(), n.getEnv(), n.getClusterName())) {\n    // grant or drop this entry; do not submit it\n  }\n}","typeGuard":"null","tryCatchPattern":"try {\n  client.withUserToken(token).createNamespaces(namespaces);\n} catch (HttpServerErrorException.Forbidden e) {\n  // Create namespace permission is required -> grant CreateNamespace and retry\n}","preventionTips":["Grant CreateNamespace to automation tokens that provision namespaces.","Pre-check create permission per batch entry to avoid partial failures.","Keep create vs modify roles distinct; create is typically more privileged."],"tags":["apollo-portal","openapi","permission","access-denied","namespace","create","user-token"],"backgroundTag":null,"analyzedSha":"d95fc18d112589efc09ddcbe1507047584d55251","analyzedAt":"2026-08-14T04:00:05.477Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}