{"record":{"id":"23e8f894a3b1602c","repo":"different-ai/openwork","slug":"only-the-workspace-owner-can-transfer-ownership","errorCode":null,"errorMessage":"Only the workspace owner can transfer ownership.","messagePattern":"Only the workspace owner can transfer ownership\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ee/apps/den-web/app/(den)/dashboard/_providers/org-dashboard-provider.tsx","lineNumber":720,"sourceCode":"    ensureTargetIsNotOwner(memberId);\n\n    await runMutation(\"remove-member\", async () => {\n      ensureActiveOrganizationSelected();\n      const { response, payload } = await requestJson(\n        `/v1/members/${encodeURIComponent(memberId)}`,\n        { method: \"DELETE\" },\n        12000,\n      );\n\n      if (response.status !== 204 && !response.ok) {\n        throw getRequestError(payload, response, `Failed to remove member (${response.status}).`);\n      }\n    });\n  }\n\n  async function transferOwnership(memberId: string) {\n    if (!getCurrentAccess().canTransferOwnership) {\n      throw new Error(\"Only the workspace owner can transfer ownership.\");\n    }\n    const target = ensureTargetIsNotOwner(memberId);\n    const targetAccess = getOrgAccessFlags(target?.role ?? \"member\", target?.isOwner ?? false, orgContext?.roles);\n    if (!target || !target.joinedAt || !targetAccess.isSuperAdmin) {\n      throw new Error(\"Ownership can only be transferred to an active super-admin.\");\n    }\n\n    await runMutation(\"transfer-ownership\", async () => {\n      ensureActiveOrganizationSelected();\n      const { response, payload } = await requestJson(\n        `/v1/members/${encodeURIComponent(memberId)}/transfer-ownership`,\n        { method: \"POST\", body: JSON.stringify({}) },\n        12000,\n      );\n\n      if (!response.ok) {\n        throw getRequestError(payload, response, `Failed to transfer ownership (${response.status}).`);\n      }","sourceCodeStart":702,"sourceCodeEnd":738,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/ee/apps/den-web/app/(den)/dashboard/_providers/org-dashboard-provider.tsx#L702-L738","documentation":"transferOwnership is restricted to the current organization owner via access.canTransferOwnership. Any other member (including super-admins who are not the owner) throws \"Only the workspace owner can transfer ownership.\" before target validation. Ownership transfer is a single-owner action by design.","triggerScenarios":"Calling transferOwnership(memberId) (e.g. from handleTransferOwnership) when the signed-in member is a super-admin or admin but not the organization owner, so canTransferOwnership is false.","commonSituations":"A super-admin assumes they can hand off ownership; an admin tries to resolve an owner leaving the team; the previous owner was already transferred and orgContext still lists the caller as owner.","solutions":["Have the current organization owner perform the transfer.","Verify who the owner is on the Members screen (owner flag) before attempting.","Refresh org context if ownership was recently transferred.","Show the transfer control only to members whose access flags include canTransferOwnership."],"exampleFix":"// before\n<Button onClick={() => handleTransferOwnership(member.id)}>Make owner</Button>\n\n// after\n{access.canTransferOwnership && (\n  <Button onClick={() => handleTransferOwnership(member.id)}>Make owner</Button>\n)}","handlingStrategy":"validation","validationCode":"if (!access.canTransferOwnership) return; // only the owner sees transfer controls","typeGuard":null,"tryCatchPattern":"try {\n  await transferOwnership(memberId);\n} catch (e) {\n  if (e instanceof Error && /transfer ownership|super-admin/.test(e.message)) {\n    toast(e.message);\n  } else throw e;\n}","preventionTips":["Expose the transfer action only to the current owner.","Show the owner flag in the member list so users know who can transfer.","Refetch org context after any ownership change."],"tags":["authorization","rbac","ownership"],"backgroundTag":"insufficient-permissions","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}