immich-app/immich · error · Error
User not found
Error message
User not found
What it means
Thrown by NotificationService.sendTestEmail when the user repository returns no (non-deleted) user for the given id. The service raises a plain Error('User not found') before attempting SMTP verification, so no test email can be prepared for a nonexistent recipient.
Solutions
- Confirm the target user id exists and is not soft-deleted (list users via the admin API and use a current id)
- Refresh the admin UI user list to drop stale ids
- If the user was deleted, restore them or pick an active admin account for the test email
- Check you are calling the correct Immich instance/environment
Example fix
// before await api.notificationApi.sendTestEmail(deletedUserId, smtpDto); // throws 'User not found' // after const users = await api.userApi.getAllUsers(false); // non-deleted users const target = users.find(u => u.email === 'admin@example.com'); await api.notificationApi.sendTestEmail(target.id, smtpDto);
Defensive patterns
Strategy: validation
Validate before calling
const users = await api.userApi.getAllUsers(false); // exclude deleted
const target = users.find(u => u.id === userId);
if (!target) throw new Error(`User ${userId} not found or deleted; pick an active user`); Type guard
function isActiveUser(user) {
return !!user && typeof user.id === 'string' && user.id.length > 0 && user.deletedAt == null;
} Try / catch
try {
await api.notificationApi.sendTestEmail(userId, smtpDto);
} catch (e) {
if (String(e.message).includes('User not found')) {
console.warn(`User ${userId} missing/deleted; re-select recipient from user list`);
} else throw e;
} Prevention
- Resolve user ids from a fresh user-list API call, not cached UI state
- Exclude soft-deleted users when picking a test-email recipient
- Re-fetch users after account deletions before sending test emails
- Confirm you are targeting the correct Immich instance/environment
When it happens
Trigger: Calling the test-email endpoint with a user id that does not exist or belongs to a soft-deleted user (withDeleted: false lookup).
Common situations: Sending a test email right after a user account was deleted; stale id cached in the admin UI from before a user was removed; id copied from another Immich instance/environment; passing the wrong id type or truncated id.
Understand the failure class
Background: "User not found", "Invalid user", and "does not exist": what missing-user lookup errors mean across Rocket.Chat, LiteLLM, Phabricator, rustfs, and pnpm — this error's family across 10 libraries.
Related errors
- Invalid user
- User not found
- Album not shared with user
- Asset media not found
- Asset metadata is not yet ready for streaming
AI-assisted analysis of immich-app/immich@e55ac299a4 (2026-09-15).
Data as JSON: /api/errors/37b8a27e19b21a94.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/services/notification.service.ts:262
level: NotificationLevel.Info,
title: 'Cluster Group Request',
description: `${senderName} asked you to join their cluster group`,
data: JSON.stringify({ clusterGroupId }),
});
this.websocketRepository.clientSend('on_notification', userId, mapNotification(item));
}
@OnEvent({ name: 'SessionDelete' })
onSessionDelete({ sessionId }: ArgOf<'SessionDelete'>) {
// after the response is sent
setTimeout(() => this.websocketRepository.clientSend('on_session_delete', sessionId, sessionId), 500);
}
async sendTestEmail(id: string, dto: SystemConfigSmtpDto, tempTemplate?: string) {
const user = await this.userRepository.get(id, { withDeleted: false });
if (!user) {
throw new Error('User not found');
}
try {
await this.emailRepository.verifySmtp(dto.transport);
} catch (error) {
throw new BadRequestException('Failed to verify SMTP configuration', { cause: error });
}
const { server } = await this.getConfig({ withCache: false });
const { html, text } = await this.emailRepository.renderEmail({
template: EmailTemplate.TEST_EMAIL,
data: {
baseUrl: getExternalDomain(server),
displayName: user.name,
},
customTemplate: tempTemplate!,
});
const { messageId } = await this.emailRepository.sendEmail({View on GitHub (pinned to e55ac299a4)