{"record":{"id":"5f4f1e179ae5e464","repo":"immich-app/immich","slug":"user-not-found-5f4f1e","errorCode":null,"errorMessage":"User not found","messagePattern":"User not found","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"server/src/services/user.service.ts","lineNumber":46,"sourceCode":"export class UserService extends BaseService {\n  async search(auth: AuthDto): Promise<UserResponseDto[]> {\n    const config = await this.getConfig({ withCache: false });\n\n    let users;\n    if (auth.user.isAdmin || config.server.publicUsers) {\n      users = await this.userRepository.getList({ withDeleted: false });\n    } else {\n      const authUser = await this.userRepository.get(auth.user.id, {});\n      users = authUser ? [authUser] : [];\n    }\n\n    return users.map((user) => mapUser(user));\n  }\n\n  async getMe(auth: AuthDto): Promise<UserAdminResponseDto> {\n    const user = await this.userRepository.get(auth.user.id, {});\n    if (!user) {\n      throw new BadRequestException('User not found');\n    }\n\n    return mapUserAdmin(user);\n  }\n\n  getCalendarHeatmap(auth: AuthDto, dto: CalendarHeatmapDto): Promise<CalendarHeatmapResponseDto> {\n    return getCalendarHeatmap(auth.user.id, dto, { asset: this.assetRepository });\n  }\n\n  async updateMe({ user }: AuthDto, dto: UserUpdateMeDto): Promise<UserAdminResponseDto> {\n    if (dto.email) {\n      const duplicate = await this.userRepository.getByEmail(dto.email);\n      if (duplicate && duplicate.id !== user.id) {\n        this.logger.warn('Email already in use by another account');\n        throw new BadRequestException('Email is not available');\n      }\n    }\n","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/immich-app/immich/blob/199723261c6ffa897fec8ccdaea6359e39c37cc3/server/src/services/user.service.ts#L28-L64","documentation":"A BadRequestException (HTTP 400) thrown by UserService.getMe when the authenticated user's record cannot be loaded from the database. The auth guard already validated the session/JWT, so reaching this branch means the user row is gone between authentication and the getMe query. It is a data-integrity signal rather than a normal client error.","triggerScenarios":"GET /users/me issued after the user was soft- or hard-deleted (e.g., by an admin) but the client still holds a valid session token. Also reachable via test harnesses that authenticate then delete the user, or a race where a deletion job commits between auth and the repository.get call.","commonSituations":"Stale tokens in a browser after an admin deletes the account; integration tests that delete users mid-flow; database restores that drop user rows but keep sessions; multi-instance setups where deletion replication lags.","solutions":["If this is an end-user client, treat it as a forced logout: clear the local session/token and redirect to login.","If you are an admin automating user lifecycle, ensure no getMe calls are in flight when you delete a user; tear down sessions first.","Check the user table for the id in the token to confirm whether the row was deleted or the id is malformed.","In tests, re-authenticate or skip getMe after deleting the acting user."],"exampleFix":"// before\nconst me = await api.getUserMe(); // 400 'User not found'\n\n// after\ntry {\n  const me = await api.getUserMe();\n} catch (e) {\n  if (e.status === 400 && e.message === 'User not found') {\n    await auth.clearSession();\n    router.push('/login');\n    return;\n  }\n  throw e;\n}","handlingStrategy":"try-catch","validationCode":"// No client-side validation can guarantee the row exists; verify right before the call\nconst stillExists = await adminApi.getUser(authUserId);\nif (!stillExists) { await clearSession(); return; }","typeGuard":"const isUserMissingError = (e: unknown): boolean =>\n  typeof e === 'object' && e !== null && (e as any).status === 400 && (e as any).message === 'User not found';","tryCatchPattern":"try {\n  return await api.getUserMe();\n} catch (e) {\n  if (isUserMissingError(e)) {\n    await auth.clearSession();\n    redirectToLogin();\n    return null;\n  }\n  throw e;\n}","preventionTips":["Treat 'User not found' on getMe as a forced logout, not a retryable error.","In tests, never call getMe after deleting the acting user.","When deleting users administratively, revoke their sessions in the same operation to avoid stale-token calls."],"tags":["user","authentication","data-integrity","nestjs"],"backgroundTag":null,"analyzedSha":"199723261c6ffa897fec8ccdaea6359e39c37cc3","analyzedAt":"2026-08-12T04:54:27.085Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}