different-ai/openwork · error

The owner role cannot be assigned from this action.

Error message

The owner role cannot be assigned from this action.

What it means

ensureRoleCanBeAssigned blocks any role mutation whose target role resolves to the canonical owner role via roleIncludesCanonicalRole, throwing 'The owner role cannot be assigned from this action.' Owner is transferred through a dedicated flow, not invites/role edits/role CRUD. It gates inviteMember, updateMemberRole, createRole, and updateRole.

Source

Thrown at ee/apps/den-web/app/(den)/dashboard/_providers/org-dashboard-provider.tsx:133

      orgContext?.roles,
    );
  }

  function ensureCanManageSettings() {
    if (!getCurrentAccess().canManageSettings) {
      throw new Error("Only workspace owners and super-admins can change settings.");
    }
  }

  function ensureCanDeleteOrganization() {
    if (!getCurrentAccess().canDeleteOrganization) {
      throw new Error("Only the workspace owner can delete this organization.");
    }
  }

  function ensureRoleCanBeAssigned(role: string) {
    if (roleIncludesCanonicalRole(role, "owner")) {
      throw new Error("The owner role cannot be assigned from this action.");
    }
  }

  function ensureTargetIsNotOwner(memberId: string) {
    const target = orgContext?.members.find((member) => member.id === memberId) ?? null;
    if (target?.isOwner) {
      throw new Error("The workspace owner cannot be changed or removed from this action.");
    }
    return target;
  }

  function shouldRefreshRolesForPage(org: DenOrgSummary) {
    const isMembersPage = pathname === "/dashboard/members" || pathname === "/dashboard/manage-members";
    return isMembersPage && getOrgAccessFlags(org.role, false).isAdmin;
  }

  async function loadOrgDirectory() {
    const { response, payload } = await requestJson("/v1/me/orgs", { method: "GET" }, 12000);

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Choose a non-owner role (admin/member/custom) for the invite or role change.
  2. Use the dedicated ownership-transfer flow to change who owns the organization.
  3. Remove owner-inherited permissions from custom roles in createRole/updateRole.
  4. Update the UI role picker to exclude the owner role from assignable options.
  5. If scripting, filter role payloads to exclude the owner canonical role before calling.

Example fix

// before
await updateMemberRole(memberId, "owner");
// after
await updateMemberRole(memberId, "admin"); // ownership transfer uses the dedicated transfer flow
Defensive patterns

Strategy: validation

Validate before calling

import { roleIncludesCanonicalRole } from "..."; // reuse provider helper
function isAssignableRole(role: string): boolean {
  return !roleIncludesCanonicalRole(role, "owner");
}
if (!isAssignableRole(selectedRole)) return; // exclude from picker

Type guard

null

Try / catch

try {
  await updateMemberRole(memberId, role);
} catch (e) {
  if (e instanceof Error && e.message.includes("owner role cannot be assigned")) {
    showToast("Use the ownership transfer flow to change the owner.");
  } else throw e;
}

Prevention

When it happens

Trigger: Inviting a member with a role that includes the owner canonical role, updating a member's role to owner, or creating/editing a custom role that includes the owner canonical role — all rejected to prevent implicit ownership transfer.

Common situations: A UI role picker that lists the owner role, a custom-role editor that allows toggling owner-granted permissions, an API/script batching member updates that includes an owner assignment, or migrating roles from another system that had owner as an assignable role.

Related errors


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/ced4bbf4564edec3. Report an issue: GitHub.