weaviate/weaviate · warning

can only create roles with less or equal permissions as the

Error message

can only create roles with less or equal permissions as the current user: %w

What it means

RBAC guard thrown by authorizeRoleScopes when a principal attempts to create or modify a role whose permissions exceed the caller's own privileges. Weaviate forbids privilege escalation: a role's combined permissions must be a subset of the current user's effective permissions. The wrapped error details which permission was excessive.

Source

Thrown at adapters/handlers/rest/authz/handlers_authz.go:138

	if !confinedToNamespace {
		if err = h.authorizer.Authorize(ctx, principal, authorization.VerbWithScope(originalVerb, authorization.ROLE_SCOPE_ALL), authorization.Roles(roleName)...); err == nil {
			return nil
		}
	}

	// Check if user can manage roles with matching permissions
	if err = h.authorizer.Authorize(ctx, principal, authorization.VerbWithScope(originalVerb, authorization.ROLE_SCOPE_MATCH), authorization.Roles(roleName)...); err == nil {
		// Verify user has all permissions they're trying to grant
		var errs error
		for _, policy := range policies {
			if err := h.authorizer.AuthorizeSilent(ctx, principal, policy.Verb, policy.Resource); err != nil {
				errs = errors.Join(errs, err)
			}
		}
		return errs
	}

	return fmt.Errorf("can only create roles with less or equal permissions as the current user: %w", err)
}

// validateLocalRoleAssignment blocks assigning a namespace-local role unless the
// caller is confined to that role's namespace. A local role is managed entirely
// within its namespace, so a global operator (and any cross-namespace caller)
// cannot assign it; global roles carry no namespace and assign anywhere. This is
// what keeps a namespace1 role from ever reaching a namespace2 (or global)
// subject. No-op on NS-disabled clusters, where ':' is a valid name character.
func (h *authZHandlers) validateLocalRoleAssignment(principal *models.Principal, roleNames []string) error {
	if !h.namespacesEnabled {
		return nil
	}
	callerNS := namespacing.ConfinedNamespace(principal)
	for _, roleName := range roleNames {
		if ns := namespacing.NamespaceFromQualified(roleName); ns != "" && ns != callerNS {
			return fmt.Errorf("a namespace-local role can only be assigned by an administrator of its own namespace")
		}
	}

View on GitHub (pinned to 75aa4b6d11)

Solutions

  1. Grant the calling user (or its role) the permissions being assigned to the new role, then retry
  2. Reduce the new role's permissions to a subset of the caller's own permissions
  3. Perform role management with a root/admin-level identity
  4. Inspect the wrapped error to identify the exact offending permission

Example fix

// before
// caller has only collections read; creating role with objects create permission
createRole("writer", perms=[{action:"create_objects",...}]) // denied
// after
// first grant caller create_objects, or scope the new role to:
createRole("reader", perms=[{action:"read_objects",...}]) // subset of caller perms
Defensive patterns

Strategy: validation

Validate before calling

// Go: intersect desired role permissions with the caller's own before create/modify
mine := effectivePermissionsOf(principal)
for _, p := range desiredPerms {
	if !containsPermission(mine, p) {
		return fmt.Errorf("cannot grant %v: exceeds caller's own permissions", p)
	}
}

Type guard

func isSubset(desired, mine []Permission) bool {
	set := map[Permission]bool{}
	for _, m := range mine {
		set[m] = true
	}
	for _, d := range desired {
		if !set[d] {
			return false
		}
	}
	return true
}

Try / catch

err := authz.CreateRole(ctx, name, perms)
if err != nil && strings.Contains(err.Error(), "less or equal permissions") {
	// inspect wrapped error for the offending permission, drop it or elevate caller
	return fmt.Errorf("role exceeds caller privileges: %v", err)
}

Prevention

When it happens

Trigger: createRole, addPermissions, removePermissions, or deleteRole called (directly or via authorizeRoleRead/resolveRoleForRead) where the target role includes a permission (action, resource type, or scope) the calling user does not itself hold.

Common situations: Admin holding cluster-scoped permissions tries to create a role with data-level permissions they lack; automation tokens with narrow scopes attempting to define broad roles; namespace-confined users creating global roles; permission typo introducing an action outside the caller's set.

Related errors


AI-assisted analysis of weaviate/weaviate@75aa4b6d11 (2026-09-04). Data as JSON: /api/errors/ea7c4cfaf0102120. Report an issue: GitHub.