{"record":{"id":"746d10729c52550f","repo":"toeverything/AFFiNE","slug":"user-not-found-746d10","errorCode":"user_not_found","errorMessage":"User not found.","messagePattern":"User not found\\.","errorType":"exception","errorClass":"UserNotFound","httpStatus":404,"severity":"error","filePath":"packages/backend/server/src/core/user/resolver.ts","lineNumber":119,"sourceCode":"  })\n  @Public()\n  async getPublicUserById(\n    @Args('id', { type: () => String }) id: string\n  ): Promise<PublicUserType | null> {\n    return await this.models.user.getPublicUser(id);\n  }\n\n  @Mutation(() => UserType, {\n    name: 'uploadAvatar',\n    description: 'Upload user avatar',\n  })\n  async uploadAvatar(\n    @CurrentUser() user: CurrentUser,\n    @Args({ name: 'avatar', type: () => GraphQLUpload })\n    avatar: FileUpload\n  ) {\n    if (!user) {\n      throw new UserNotFound();\n    }\n\n    const avatarBuffer = await readBufferWithLimit(\n      avatar.createReadStream(),\n      5 * OneMB\n    );\n    const contentType = sniffMime(avatarBuffer, avatar.mimetype)?.toLowerCase();\n    if (!contentType || !contentType.startsWith('image/')) {\n      throw new ImageFormatNotSupported({ format: contentType || 'unknown' });\n    }\n\n    let processedAvatarBuffer: Buffer;\n    try {\n      processedAvatarBuffer = await processImage(avatarBuffer, 512, false);\n    } catch {\n      throw new ImageFormatNotSupported({ format: contentType });\n    }\n","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/26c515e050211269e911f7d9cfe162a26c83ed98/packages/backend/server/src/core/user/resolver.ts#L101-L137","documentation":"Thrown by the uploadAvatar GraphQL mutation when the @CurrentUser() decorator resolves to a falsy value. This is a defensive auth check inside the resolver body — the mutation is reachable yet no authenticated user was attached, so there is no owner to attach the avatar to. (The same code shape repeats in removeAvatar.)","triggerScenarios":"The uploadAvatar mutation is invoked without a valid authenticated session, so the CurrentUser argument is null/undefined.","commonSituations":"Session token expired before the mutation was sent; GraphQL operation issued before login completed; auth guard misconfigured to allow the mutation through without resolving a user.","solutions":["Ensure the client sends a valid auth token with the uploadAvatar mutation.","Re-authenticate on token expiry before retrying the avatar upload.","Verify the GraphQL auth guard resolves CurrentUser for this mutation."],"exampleFix":"// before — uploading after token expiry\nawait apollo.mutate({ mutation: UPLOAD_AVATAR, variables: { avatar } });\n\n// after — refresh session first\nawait refreshSessionIfNeeded();\nawait apollo.mutate({ mutation: UPLOAD_AVATAR, variables: { avatar } });","handlingStrategy":"validation","validationCode":"if (!currentUser) { await refreshSession(); return; }\nawait uploadAvatar(avatar);","typeGuard":"function hasCurrentUser(user?: CurrentUser | null): user is CurrentUser {\n  return Boolean(user?.id);\n}","tryCatchPattern":"try {\n  await apollo.mutate({ mutation: UPLOAD_AVATAR, variables: { avatar } });\n} catch (e) {\n  if (e?.code === 'user_not_found' || e?.code === 'authentication_required') { await refreshSession(); return; }\n  throw e;\n}","preventionTips":["Send a valid auth token with avatar mutations.","Refresh the session on token expiry before retrying.","Verify the GraphQL auth guard resolves CurrentUser for the mutation."],"tags":["user","graphql","auth","avatar"],"backgroundTag":null,"analyzedSha":"26c515e050211269e911f7d9cfe162a26c83ed98","analyzedAt":"2026-08-12T13:15:16.447Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}