toeverything/AFFiNE · error · Error
Cannot remove the last doc owner grant.
Error message
Cannot remove the last doc owner grant.
What it means
Thrown by DocPermissionModel.delete (permission-write.ts:646) when removing a user's grant would leave the doc with zero user-owner grants. Mirrors the workspace-owner invariant at the doc level: a doc must always retain at least one owner grant. Guarded by a SELECT ... FOR UPDATE on owner rows. Plain Error.
Source
Thrown at packages/backend/server/src/models/permission-write.ts:646
where: {
workspaceId,
docId,
principalType: 'user',
principalId: userId,
role: 'owner',
},
});
const otherOwners = await this.db.docGrant.count({
where: {
workspaceId,
docId,
principalType: 'user',
principalId: { not: userId },
role: 'owner',
},
});
if (deletingOwner > 0 && otherOwners === 0) {
throw new Error('Cannot remove the last doc owner grant.');
}
return await this.db.docGrant.deleteMany({
where: {
workspaceId,
docId,
principalType: 'user',
principalId: userId,
},
});
}
}
View on GitHub (pinned to 26c515e050)
Solutions
- Transfer doc ownership to another user first (grantUserRole with DocRole.Owner), then revoke the old owner.
- If the doc should no longer exist, delete the doc rather than removing its last owner grant.
- Before deleting, ensure at least one other user owner grant exists.
Example fix
// before await models.docPermission.delete(wsId, docId, ownerUserId); // after await models.docPermission.grantUserRole(wsId, docId, otherUserId, DocRole.Owner); await models.docPermission.delete(wsId, docId, ownerUserId);
Defensive patterns
Strategy: validation
Validate before calling
async function safeRemoveDocOwner(models, wsId: string, docId: string, userId: string) {
const otherOwners = await models.db.docGrant.count({
where: { workspaceId: wsId, docId, principalType: 'user', principalId: { not: userId }, role: 'owner' },
});
if (otherOwners === 0) {
throw new Error('Refusing to remove the last doc owner; transfer ownership first.');
}
return models.docPermission.delete(wsId, docId, userId);
} Prevention
- Ensure another user owner grant exists before removing the last one.
- Transfer doc ownership before revoking the current owner.
- Delete the doc rather than stripping its last owner when the doc is no longer needed.
When it happens
Trigger: Revoking the only remaining doc owner's grant via DocPermissionModel.delete; deleting the sole owner's doc grant; cascading a member removal that drops the last owner grant.
Common situations: Owner tries to leave a doc they alone own; a cleanup script removes all grants on a doc; ownership transfer was attempted through a code path that didn't first add a new owner.
Related errors
- Cannot remove the last active workspace owner.
- can_not_batch_grant_doc_owner_permissions
- doc_action_denied
- expect_to_grant_doc_user_roles
- new_owner_is_not_active_member
AI-assisted analysis of toeverything/AFFiNE@26c515e050 (2026-08-12).
Data as JSON: /api/errors/fbcbae6306d02aab.
Report an issue: GitHub.