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 the deprecated workspaceRolePermissions query when the access-control call ac.user(user.id).workspace(id).permissions() returns no role — the caller has no role (membership) in that workspace, so permissions cannot be resolved.

Solutions

  1. Migrate the client to read permissions from the workspace type's permissions field (the query is deprecated).
  2. Ensure the user is an active member of the workspace before querying its role permissions.
  3. Handle space_access_denied by routing the user to the join/request-access flow instead of the workspace UI.
Defensive patterns

Strategy: validation

Validate before calling

// Ensure membership before querying role permissions
const mine = await gql.request(GET_WORKSPACES);
if (!mine.workspaces.some(w => w.id === workspaceId)) {
  routeToJoinOrLanding(workspaceId);
}

Type guard

const isSpaceAccessDenied = (e: unknown): boolean =>
  getGraphqlErrorCode(e) === 'space_access_denied';

Try / catch

try {
  const perms = await gql.request(WORKSPACE_ROLE_PERMISSIONS, { id: workspaceId });
} catch (e) {
  if (isSpaceAccessDenied(e)) routeToJoinOrLanding(workspaceId);
}

Prevention

When it happens

Trigger: Querying workspaceRolePermissions(id) for a workspace the current user is not a member of (never joined, was removed, or wrong id).

Common situations: Query is deprecated in favor of WorkspaceType[permissions]; clients still on the old query hit it after losing membership; cross-workspace deep links route a non-member into the permissions query.

Related errors


AI-assisted analysis of toeverything/AFFiNE@2af30773ae (2026-08-18). Data as JSON: /api/errors/e89cbabaa36c111c. Report an issue: GitHub.

Appendix: source

Thrown at packages/backend/server/src/core/workspaces/resolvers/workspace.ts:196

    return workspace;
  }

  @Query(() => WorkspaceRolePermissions, {
    description: 'Get workspace role permissions',
    deprecationReason: 'use WorkspaceType[permissions] instead',
  })
  async workspaceRolePermissions(
    @CurrentUser() user: CurrentUser,
    @Args('id') id: string
  ): Promise<WorkspaceRolePermissions> {
    const { role, permissions } = await this.ac
      .user(user.id)
      .workspace(id)
      .permissions();

    if (!role) {
      throw new SpaceAccessDenied({ spaceId: id });
    }

    return {
      role,
      permissions: mapPermissionsToGraphqlPermissions(permissions),
    };
  }

  @Mutation(() => WorkspaceType, {
    description: 'Create a new workspace',
  })
  async createWorkspace(
    @CurrentUser() user: CurrentUser,
    // we no longer support init workspace with a preload file
    // use sync system to uploading them once created
    @Args({ name: 'init', type: () => GraphQLUpload, nullable: true })
    init: FileUpload | null
  ) {

View on GitHub (pinned to 2af30773ae)