{"record":{"id":"455ab1b82d515ae9","repo":"immich-app/immich","slug":"notification-not-found","errorCode":null,"errorMessage":"Notification not found","messagePattern":"Notification not found","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"server/src/services/notification.service.ts","lineNumber":58,"sourceCode":"  }\n\n  async updateAll(auth: AuthDto, dto: NotificationUpdateAllDto) {\n    await this.requireAccess({ auth, ids: dto.ids, permission: Permission.NotificationUpdate });\n    await this.notificationRepository.updateAll(dto.ids, {\n      readAt: dto.readAt,\n    });\n  }\n\n  async deleteAll(auth: AuthDto, dto: NotificationDeleteAllDto) {\n    await this.requireAccess({ auth, ids: dto.ids, permission: Permission.NotificationDelete });\n    await this.notificationRepository.deleteAll(dto.ids);\n  }\n\n  async get(auth: AuthDto, id: string) {\n    await this.requireAccess({ auth, ids: [id], permission: Permission.NotificationRead });\n    const item = await this.notificationRepository.get(id);\n    if (!item) {\n      throw new BadRequestException('Notification not found');\n    }\n    return mapNotification(item);\n  }\n\n  async update(auth: AuthDto, id: string, dto: NotificationUpdateDto) {\n    await this.requireAccess({ auth, ids: [id], permission: Permission.NotificationUpdate });\n    const item = await this.notificationRepository.update(id, {\n      readAt: dto.readAt,\n    });\n    return mapNotification(item);\n  }\n\n  async delete(auth: AuthDto, id: string) {\n    await this.requireAccess({ auth, ids: [id], permission: Permission.NotificationDelete });\n    await this.notificationRepository.delete(id);\n  }\n\n  @OnJob({ name: JobName.NotificationsCleanup, queue: QueueName.BackgroundTask })","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/immich-app/immich/blob/199723261c6ffa897fec8ccdaea6359e39c37cc3/server/src/services/notification.service.ts#L40-L76","documentation":"NotificationService.get fetches a single notification by id after the access check passes; if notificationRepository.get returns null (no such notification, or it does not belong to a context the user can read), it throws 400 BadRequestException 'Notification not found'. The 400 (rather than 404) is an Immich convention for these lookups.","triggerScenarios":"GET /notifications/{id} for an id that does not exist or that the access scope does not cover. Common with a stale notification id in the UI after it was deleted, or a hand-crafted request.","commonSituations":"User dismissed/deleted a notification but the client still references it; wrong id copied; another admin cleared all notifications.","solutions":["Refresh the notification list (GET /notifications) and operate only on current ids.","Handle the 400 gracefully in the client and drop the stale reference.","Confirm the id is a valid UUID."],"exampleFix":"// before\napi.notifications.get('stale-id');\n// after\nconst list = await api.notifications.list();\nawait api.notifications.get(list[0].id);","handlingStrategy":"validation","validationCode":"const list = await api.notificationApi.list();\nif (!list.some((n) => n.id === id)) {\n  throw new Error(`Notification ${id} not found`);\n}\nawait api.notificationApi.get(id);","typeGuard":"const notificationExists = (id: string, items: { id: string }[]) =>\n  items.some((n) => n.id === id);","tryCatchPattern":"try {\n  return await api.notificationApi.get(id);\n} catch (e) {\n  if (e.status === 400 && /Notification not found/.test(e.message)) {\n    // refresh the list and drop the stale id\n  } else throw e;\n}","preventionTips":["Operate on notifications from a freshly fetched list.","Handle 400 by invalidating the local notification cache.","Use UUID validation client-side."],"tags":["api","notification","validation","not-found","bad-request","immich","nestjs"],"backgroundTag":null,"analyzedSha":"199723261c6ffa897fec8ccdaea6359e39c37cc3","analyzedAt":"2026-08-12T04:54:27.085Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}