{"record":{"id":"26072be57ec95418","repo":"different-ai/openwork","slug":"the-workspace-owner-cannot-be-changed-or-removed-f","errorCode":null,"errorMessage":"The workspace owner cannot be changed or removed from this action.","messagePattern":"The workspace owner cannot be changed or removed from this action\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ee/apps/den-web/app/(den)/dashboard/_providers/org-dashboard-provider.tsx","lineNumber":140,"sourceCode":"    }\n  }\n\n  function ensureCanDeleteOrganization() {\n    if (!getCurrentAccess().canDeleteOrganization) {\n      throw new Error(\"Only the workspace owner can delete this organization.\");\n    }\n  }\n\n  function ensureRoleCanBeAssigned(role: string) {\n    if (roleIncludesCanonicalRole(role, \"owner\")) {\n      throw new Error(\"The owner role cannot be assigned from this action.\");\n    }\n  }\n\n  function ensureTargetIsNotOwner(memberId: string) {\n    const target = orgContext?.members.find((member) => member.id === memberId) ?? null;\n    if (target?.isOwner) {\n      throw new Error(\"The workspace owner cannot be changed or removed from this action.\");\n    }\n    return target;\n  }\n\n  function shouldRefreshRolesForPage(org: DenOrgSummary) {\n    const isMembersPage = pathname === \"/dashboard/members\" || pathname === \"/dashboard/manage-members\";\n    return isMembersPage && getOrgAccessFlags(org.role, false).isAdmin;\n  }\n\n  async function loadOrgDirectory() {\n    const { response, payload } = await requestJson(\"/v1/me/orgs\", { method: \"GET\" }, 12000);\n    if (!response.ok) {\n      throw new Error(getErrorMessage(payload, `Failed to load organizations (${response.status}).`));\n    }\n\n    return parseOrgListPayload(payload);\n  }\n","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/ee/apps/den-web/app/(den)/dashboard/_providers/org-dashboard-provider.tsx#L122-L158","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","solutions":["Skip the owner in bulk role-change/removal operations.","Disable role/edit and remove controls for rows where member.isOwner is true.","Refresh the members list if ownership recently transferred to ensure isOwner is current.","Use the dedicated ownership-transfer flow if the owner should change, then re-run the action.","Handle the thrown error gracefully in batch loops so one owner hit doesn't abort the rest."],"exampleFix":"// before\nfor (const id of memberIds) await removeMember(id);\n// after\nfor (const id of memberIds) {\n  const m = members.find((x) => x.id === id);\n  if (m?.isOwner) continue;\n  await removeMember(id);\n}","handlingStrategy":"type-guard","validationCode":"const target = members.find((m) => m.id === memberId);\nif (!target || target.isOwner) return; // skip owner in bulk ops","typeGuard":"function isMutableMember(m: { id: string; isOwner?: boolean }): boolean {\n  return !m.isOwner;\n}","tryCatchPattern":"try {\n  await removeMember(memberId);\n} catch (e) {\n  if (e instanceof Error && e.message.includes(\"workspace owner cannot be\")) {\n    showToast(\"The workspace owner cannot be removed.\");\n  } else throw e;\n}","preventionTips":["Disable row actions where member.isOwner is true.","Skip the owner in bulk role-change/removal scripts.","Refresh member data after ownership transfers to keep isOwner accurate.","Use the dedicated ownership-transfer flow before removing a former owner's stale flags."],"tags":["permissions","rbac","organization","guard"],"backgroundTag":"forbidden-role-assignment","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}