toeverything/AFFiNE · error · UserNotFound
user_not_found
user_not_found
Error message
User not found.
What it means
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.)
Source
Thrown at packages/backend/server/src/core/user/resolver.ts:119
})
@Public()
async getPublicUserById(
@Args('id', { type: () => String }) id: string
): Promise<PublicUserType | null> {
return await this.models.user.getPublicUser(id);
}
@Mutation(() => UserType, {
name: 'uploadAvatar',
description: 'Upload user avatar',
})
async uploadAvatar(
@CurrentUser() user: CurrentUser,
@Args({ name: 'avatar', type: () => GraphQLUpload })
avatar: FileUpload
) {
if (!user) {
throw new UserNotFound();
}
const avatarBuffer = await readBufferWithLimit(
avatar.createReadStream(),
5 * OneMB
);
const contentType = sniffMime(avatarBuffer, avatar.mimetype)?.toLowerCase();
if (!contentType || !contentType.startsWith('image/')) {
throw new ImageFormatNotSupported({ format: contentType || 'unknown' });
}
let processedAvatarBuffer: Buffer;
try {
processedAvatarBuffer = await processImage(avatarBuffer, 512, false);
} catch {
throw new ImageFormatNotSupported({ format: contentType });
}
View on GitHub (pinned to 26c515e050)
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.
Example fix
// before — uploading after token expiry
await apollo.mutate({ mutation: UPLOAD_AVATAR, variables: { avatar } });
// after — refresh session first
await refreshSessionIfNeeded();
await apollo.mutate({ mutation: UPLOAD_AVATAR, variables: { avatar } }); Defensive patterns
Strategy: validation
Validate before calling
if (!currentUser) { await refreshSession(); return; }
await uploadAvatar(avatar); Type guard
function hasCurrentUser(user?: CurrentUser | null): user is CurrentUser {
return Boolean(user?.id);
} Try / catch
try {
await apollo.mutate({ mutation: UPLOAD_AVATAR, variables: { avatar } });
} catch (e) {
if (e?.code === 'user_not_found' || e?.code === 'authentication_required') { await refreshSession(); return; }
throw e;
} Prevention
- 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.
When it happens
Trigger: The uploadAvatar mutation is invoked without a valid authenticated session, so the CurrentUser argument is null/undefined.
Common situations: 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.
Related errors
AI-assisted analysis of toeverything/AFFiNE@26c515e050 (2026-08-12).
Data as JSON: /api/errors/746d10729c52550f.
Report an issue: GitHub.