different-ai/openwork · error

The workspace owner cannot be changed or removed from this a

Error message

The workspace owner cannot be changed or removed from this action.

What it means

ensureTargetIsNotOwner looks up the target member in orgContext.members and throws 'The workspace owner cannot be changed or removed from this action.' if target.isOwner is true. It protects the owner account from role changes and removal, and returns the resolved target otherwise (used by target callers too).

Source

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

    }
  }

  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);
    if (!response.ok) {
      throw new Error(getErrorMessage(payload, `Failed to load organizations (${response.status}).`));
    }

    return parseOrgListPayload(payload);
  }

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Skip the owner in bulk role-change/removal operations.
  2. Disable role/edit and remove controls for rows where member.isOwner is true.
  3. Refresh the members list if ownership recently transferred to ensure isOwner is current.
  4. Use the dedicated ownership-transfer flow if the owner should change, then re-run the action.
  5. Handle the thrown error gracefully in batch loops so one owner hit doesn't abort the rest.

Example fix

// before
for (const id of memberIds) await removeMember(id);
// after
for (const id of memberIds) {
  const m = members.find((x) => x.id === id);
  if (m?.isOwner) continue;
  await removeMember(id);
}
Defensive patterns

Strategy: type-guard

Validate before calling

const target = members.find((m) => m.id === memberId);
if (!target || target.isOwner) return; // skip owner in bulk ops

Type guard

function isMutableMember(m: { id: string; isOwner?: boolean }): boolean {
  return !m.isOwner;
}

Try / catch

try {
  await removeMember(memberId);
} catch (e) {
  if (e instanceof Error && e.message.includes("workspace owner cannot be")) {
    showToast("The workspace owner cannot be removed.");
  } else throw e;
}

Prevention

When it happens

Trigger: updateMemberRole or removeMember invoked with the owner's memberId, or code using ensureTargetIsNotOwner to resolve a member that turns out to be the owner — including attempts to demote or kick the owner even by super-admins through this action.

Common situations: Bulk member-management scripts that don't skip the owner, an admin cleaning up inactive members who happens to select the owner, a members-table UI without an isOwner guard on row actions, or stale member data where ownership recently transferred but the cache still marks the old owner.

Related errors


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