{"record":{"id":"c9f1517e7f167e24","repo":"toeverything/AFFiNE","slug":"action-forbidden-c9f151","errorCode":"action_forbidden","errorMessage":"This feature is temporarily unavailable for you.","messagePattern":"This feature is temporarily unavailable for you\\.","errorType":"exception","errorClass":"ActionForbidden","httpStatus":403,"severity":"error","filePath":"packages/backend/server/src/core/workspaces/resolvers/doc.ts","lineNumber":332,"sourceCode":"    private readonly ac: PermissionAccess,\n    private readonly models: Models,\n    private readonly cache: Cache,\n    private readonly event: EventBus,\n    private readonly runtime: BackendRuntimeProvider\n  ) {}\n\n  @ResolveField(() => WorkspaceDocMeta, {\n    description: 'Cloud page metadata of workspace',\n    complexity: 2,\n    deprecationReason: 'use [WorkspaceType.doc] instead',\n  })\n  async pageMeta(\n    @CurrentUser() me: CurrentUser,\n    @Parent() workspace: WorkspaceType,\n    @Args('pageId') pageId: string\n  ) {\n    await this.ac.user(me.id).doc(workspace.id, pageId).assert('Doc.Read');\n\n    const metadata = await this.models.doc.getAuthors(workspace.id, pageId);\n    if (!metadata) {\n      throw new DocNotFound({ spaceId: workspace.id, docId: pageId });\n    }\n\n    return {\n      createdAt: metadata.createdAt,\n      updatedAt: metadata.updatedAt,\n      createdBy: metadata.createdByUser || null,\n      updatedBy: metadata.updatedByUser || null,\n    };\n  }\n\n  @ResolveField(() => [DocType], {\n    description: 'Get public docs of a workspace',\n    complexity: 2,\n  })\n  async publicDocs(@Parent() workspace: WorkspaceType) {","sourceCodeStart":314,"sourceCodeEnd":350,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/2af30773aecd567f09b346e7b72fc69143144057/packages/backend/server/src/core/workspaces/resolvers/doc.ts#L314-L350","documentation":"publishDoc runs assertCanShare before publishing. If the acting user is currently quarantined or banned by the invite-abuse system, the action is refused with ActionForbidden and a deliberately generic message. This is an anti-abuse gate, not a permissions bug: the user may hold Doc.Publish on the workspace and still be blocked from share actions.","triggerScenarios":"A publishDoc mutation executed by an account flagged by the invite-abuse heuristics (mass invites, spam-like behavior). The server logs 'Share action blocked for quarantined actor' with the userId and context.","commonSituations":"Cloud-hosted AFFiNE accounts that tripped abuse detection; automation/scripts issuing many invite or share operations that resemble spam.","solutions":["Appeal the flag or contact support to have the quarantine lifted for the account","If the quarantine is time-based, wait for it to expire and retry","Publish from a different, unflagged account that has Doc.Publish rights on the workspace"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isActionForbidden(e: unknown): boolean {\n  return (\n    typeof e === 'object' && e !== null &&\n    (e as { extensions?: { code?: string } }).extensions?.code === 'action_forbidden'\n  );\n}","tryCatchPattern":"try {\n  await publishDoc(wsId, docId, mode);\n} catch (e) {\n  if (isActionForbidden(e)) {\n    showRestrictedMessage('Sharing is temporarily unavailable for this account.'); // do not retry\n  } else throw e;\n}","preventionTips":["Treat action_forbidden on share actions as a terminal state for that user — do not auto-retry","Surface the generic message to users; the specifics live in server logs only","Keep invite/share automation within normal volumes to avoid tripping abuse heuristics"],"tags":["forbidden","anti-abuse","publish","affine"],"backgroundTag":"user-account-restricted","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"}