toeverything/AFFiNE · error · SpaceAccessDenied
space_access_denied
space_access_denied
Error message
You do not have permission to access Space ${spaceId}. What it means
Thrown by assertWorkspaceAcceptsMemberChange when policy.getWorkspaceState(workspaceId).isReadonly is true. Member-changing operations (accepting invitations, join/leave) are blocked while the workspace is in a readonly policy state (e.g. billing suspended or admin-locked).
Solutions
- Resolve the underlying state: the workspace owner should fix billing/subscription so the workspace exits readonly.
- Retry the invitation acceptance after the workspace state returns to normal (the check re-evaluates each call).
- If you believe the state is wrong, inspect the workspace policy/quota state records for stuck flags.
Defensive patterns
Strategy: retry
Try / catch
try {
await acceptInvitation(inviteId);
} catch (e) {
if (getErrorCode(e) === 'space_access_denied') {
// workspace is locked/readonly — have the owner fix billing, then the user can retry
showNotice('This workspace is currently read-only. Ask the owner to resolve billing, then retry.');
}
} Prevention
- Treat space_access_denied during invitation acceptance as a temporary workspace state; retry after the owner restores the workspace.
- Monitor workspace quota/policy state so readonly locks are caught before invitations are sent.
When it happens
Trigger: Calling acceptInvitation (email or link path) or other member mutations on a workspace whose policy state is readonly.
Common situations: Self-hosted or cloud workspace suspended for overdue payment/expired trial; admin put the workspace in a locked state; the user retries an invitation accept while the lock is still active.
Related errors
- authentication_required
- invalid_invitation
- not_found
- bad_request
- cannot_delete_account_with_owned_team_workspace
AI-assisted analysis of toeverything/AFFiNE@4953682779 (2026-08-18).
Data as JSON: /api/errors/eb7485d51aa126fd.
Report an issue: GitHub.
Appendix: source
Thrown at packages/backend/server/src/core/workspaces/resolvers/member.ts:796
workspaceId,
user.id,
WorkspaceRole.Collaborator,
{
status: WorkspaceMemberStatus.UnderReview,
source: WorkspaceMemberSource.Link,
inviterId: inviter.id,
}
);
await this.workspaceService.sendReviewRequestNotification(role.id);
this.event.emit('workspace.members.updated', { workspaceId });
return;
}
private async assertWorkspaceAcceptsMemberChange(workspaceId: string) {
const state = await this.policy.getWorkspaceState(workspaceId);
if (state.isReadonly) {
throw new SpaceAccessDenied({ spaceId: workspaceId });
}
}
private async allocateAvailableTeamSeats(workspaceId: string, limit: number) {
if (limit <= 0) return;
await this.workspaceService.allocateSeats(workspaceId, limit);
}
}
View on GitHub (pinned to 4953682779)