{"record":{"id":"1e264b6f13df160b","repo":"toeverything/AFFiNE","slug":"mention-user-oneself-denied","errorCode":"mention_user_oneself_denied","errorMessage":"You can not mention yourself.","messagePattern":"You can not mention yourself\\.","errorType":"exception","errorClass":"MentionUserOneselfDenied","httpStatus":403,"severity":"warning","filePath":"packages/backend/server/src/core/notification/resolver.ts","lineNumber":116,"sourceCode":"  }\n\n  @Mutation(() => ID, {\n    description: 'mention user in a doc',\n  })\n  async mentionUser(\n    @CurrentUser() me: UserType,\n    @Args('input') input: MentionInput\n  ) {\n    const parsedInput = MentionNotificationCreateSchema.parse({\n      userId: input.userId,\n      body: {\n        workspaceId: input.workspaceId,\n        doc: input.doc,\n        createdByUserId: me.id,\n      },\n    });\n    if (parsedInput.userId === me.id) {\n      throw new MentionUserOneselfDenied();\n    }\n    // currentUser can update the doc\n    await this.ac\n      .user(me.id)\n      .doc(parsedInput.body.workspaceId, parsedInput.body.doc.id)\n      .assert('Doc.Update');\n    // mention user can read the doc\n    if (\n      !(await this.ac\n        .user(parsedInput.userId)\n        .doc(parsedInput.body.workspaceId, parsedInput.body.doc.id)\n        .can('Doc.Read'))\n    ) {\n      throw new MentionUserDocAccessDenied({\n        docId: parsedInput.body.doc.id,\n      });\n    }\n    const notification = await this.service.createMention(parsedInput);","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/591f874dad30887a80143a061a44bd3ca7ee3299/packages/backend/server/src/core/notification/resolver.ts#L98-L134","documentation":"The createMention mutation parses MentionNotificationCreateSchema and immediately rejects self-mentions: if input.userId equals the authenticated user's id (me.id) it throws MentionUserOneselfDenied (action_forbidden / mention_user_oneself_denied). Mentioning yourself is pointless because you are the notification recipient and the mention author at the same time.","triggerScenarios":"The mention picker returning the current user (search matches on your own name) and the client sending it; automated doc-processing that @-mentions every contributor including the author; UI tests that pick the first suggestion without filtering.","commonSituations":"Frontend mention dropdowns that don't exclude 'self' from candidate results; keyboard shortcut flows that auto-complete the top match; older clients predating this server-side check.","solutions":["Filter the current user out of mention suggestions in the UI before submission","Guard client-side: skip the createMention call when selectedUserId === currentUser.id","Show a hint ('You cannot mention yourself') when a self-mention is attempted in the picker","On catch, remove the self-mention from the doc's mention list and continue publishing"],"exampleFix":"// before\nif (mentionedUserIds.includes(me.id)) await createMention({ userId: me.id, ... });\n\n// after\nconst others = mentionedUserIds.filter(id => id !== me.id);\nfor (const userId of others) await createMention({ userId, ... });","handlingStrategy":"validation","validationCode":"if (mentionUserId === me.id) {\n  return showHint('You cannot mention yourself');\n}\nawait createMention({ userId: mentionUserId, body });","typeGuard":"function isMentionOneselfDenied(e: unknown): boolean {\n  return (e as { extensions?: { code?: string } }).extensions?.code === 'mention_user_oneself_denied';\n}","tryCatchPattern":"try {\n  await createMention(input);\n} catch (e) {\n  if (isMentionOneselfDenied(e)) return; // silently drop self-mention\n  throw e;\n}","preventionTips":["Exclude the current user from mention autocomplete results","Filter self-mentions out of any batch mention publish flow","Cover this rule in UI tests so the picker never offers self"],"tags":["notification","mention","business-rule","collaboration"],"backgroundTag":"business-rule-violation","analyzedSha":"591f874dad30887a80143a061a44bd3ca7ee3299","analyzedAt":"2026-08-18T21:16:52.546Z","contentChangedAt":"2026-08-18T21:16:52.546Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}