{"record":{"id":"e89cbabaa36c111c","repo":"toeverything/AFFiNE","slug":"space-access-denied-e89cba","errorCode":"space_access_denied","errorMessage":"You do not have permission to access Space ${spaceId}.","messagePattern":"You do not have permission to access Space (.+?)\\.","errorType":"exception","errorClass":"SpaceAccessDenied","httpStatus":403,"severity":"error","filePath":"packages/backend/server/src/core/workspaces/resolvers/workspace.ts","lineNumber":196,"sourceCode":"\n    return workspace;\n  }\n\n  @Query(() => WorkspaceRolePermissions, {\n    description: 'Get workspace role permissions',\n    deprecationReason: 'use WorkspaceType[permissions] instead',\n  })\n  async workspaceRolePermissions(\n    @CurrentUser() user: CurrentUser,\n    @Args('id') id: string\n  ): Promise<WorkspaceRolePermissions> {\n    const { role, permissions } = await this.ac\n      .user(user.id)\n      .workspace(id)\n      .permissions();\n\n    if (!role) {\n      throw new SpaceAccessDenied({ spaceId: id });\n    }\n\n    return {\n      role,\n      permissions: mapPermissionsToGraphqlPermissions(permissions),\n    };\n  }\n\n  @Mutation(() => WorkspaceType, {\n    description: 'Create a new workspace',\n  })\n  async createWorkspace(\n    @CurrentUser() user: CurrentUser,\n    // we no longer support init workspace with a preload file\n    // use sync system to uploading them once created\n    @Args({ name: 'init', type: () => GraphQLUpload, nullable: true })\n    init: FileUpload | null\n  ) {","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/2af30773aecd567f09b346e7b72fc69143144057/packages/backend/server/src/core/workspaces/resolvers/workspace.ts#L178-L214","documentation":"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.","triggerScenarios":"Querying workspaceRolePermissions(id) for a workspace the current user is not a member of (never joined, was removed, or wrong id).","commonSituations":"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.","solutions":["Migrate the client to read permissions from the workspace type's permissions field (the query is deprecated).","Ensure the user is an active member of the workspace before querying its role permissions.","Handle space_access_denied by routing the user to the join/request-access flow instead of the workspace UI."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Ensure membership before querying role permissions\nconst mine = await gql.request(GET_WORKSPACES);\nif (!mine.workspaces.some(w => w.id === workspaceId)) {\n  routeToJoinOrLanding(workspaceId);\n}","typeGuard":"const isSpaceAccessDenied = (e: unknown): boolean =>\n  getGraphqlErrorCode(e) === 'space_access_denied';","tryCatchPattern":"try {\n  const perms = await gql.request(WORKSPACE_ROLE_PERMISSIONS, { id: workspaceId });\n} catch (e) {\n  if (isSpaceAccessDenied(e)) routeToJoinOrLanding(workspaceId);\n}","preventionTips":["Migrate off the deprecated workspaceRolePermissions query to the permissions field on the workspace type.","Gate workspace-scoped queries behind a membership check from the workspace list."],"tags":["workspace","permissions","authorization","graphql","deprecated"],"backgroundTag":"authorization-denied","analyzedSha":"2af30773aecd567f09b346e7b72fc69143144057","analyzedAt":"2026-08-18T21:16:52.546Z","contentChangedAt":"2026-08-18T21:16:52.546Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}