toeverything/AFFiNE · error · CannotDeleteAccountWithOwnedTeamWorkspace

cannot_delete_account_with_owned_team_workspace

cannot_delete_account_with_owned_team_workspace

Error message

Cannot delete account. You are the owner of one or more team workspaces. Please transfer ownership or delete them first.

What it means

Thrown by UserModel.delete (user.ts:294) when the user owns any workspace that is a team workspace (isTeamWorkspace === true). Team workspaces must not be orphaned, so ownership must be transferred or the workspace deleted before the account can be removed. UserFriendlyError, code cannot_delete_account_with_owned_team_workspace, type action_forbidden, HTTP 403.

Source

Thrown at packages/backend/server/src/models/user.ts:294

    return user;
  }

  async ownedWorkspaces(id: string) {
    return await this.models.workspaceUser.getUserActiveRoles(id, {
      role: WorkspaceRole.Owner,
    });
  }

  async delete(id: string) {
    const ownedWorkspaces = await this.ownedWorkspaces(id);

    for (const ws of ownedWorkspaces) {
      const isTeamWorkspace = await this.models.workspace.isTeamWorkspace(
        ws.workspaceId
      );

      if (isTeamWorkspace) {
        throw new CannotDeleteAccountWithOwnedTeamWorkspace();
      }
    }

    await this.event.emitAsync('user.preDelete', { id });

    await this.db.workspaceInvitation.deleteMany({
      where: { inviteeUserId: id },
    });

    const user = await this.db.user.delete({ where: { id } });

    this.event.emit('user.deleted', {
      ...user,
      ownedWorkspaces: ownedWorkspaces.map(r => r.workspaceId),
    });

    return user;
  }

View on GitHub (pinned to 26c515e050)

Solutions

  1. Transfer ownership of each team workspace via setOwner to another active member.
  2. Or delete those team workspaces if they are no longer needed.
  3. Retry account deletion once no team workspace lists the user as owner. (Personal / non-team workspaces do not block deletion.)
Defensive patterns

Strategy: validation

Validate before calling

async function canDeleteAccount(models, userId: string): Promise<boolean> {
  const owned = await models.user.ownedWorkspaces(userId);
  for (const ws of owned) {
    if (await models.workspace.isTeamWorkspace(ws.workspaceId)) return false;
  }
  return true;
}

Try / catch

import { CannotDeleteAccountWithOwnedTeamWorkspace } from '../base/error/errors.gen';

try {
  await models.user.delete(id);
} catch (e) {
  if (e instanceof CannotDeleteAccountWithOwnedTeamWorkspace) {
    // list the blocking team workspaces and prompt to transfer ownership
  } else throw e;
}

Prevention

When it happens

Trigger: DELETE /user (account deletion) for a user who owns one or more team workspaces.

Common situations: Admin removes a former employee who still owns team workspaces; self-service 'delete my account' is blocked because the user forgot to hand over a team workspace; ownership of a team workspace was never transferred off the user.

Related errors


AI-assisted analysis of toeverything/AFFiNE@26c515e050 (2026-08-12). Data as JSON: /api/errors/17e78a9c13a405db. Report an issue: GitHub.