toeverything/AFFiNE · warning · NotificationNotFound
notification_not_found
notification_not_found
Error message
Notification not found.
What it means
NotificationNotFound (code=notification_not_found) thrown by markAsRead when Prisma raises P2025 (record not found) — meaning no notification row matched the (notificationId, userId) pair. The service catches P2025 specifically and rethrows as a typed NotFound; any other Prisma error is rethrown unchanged.
Source
Thrown at packages/backend/server/src/core/notification/service.ts:547
this.logger.debug(
`Invitation review declined email sent to user ${receiver.id} for workspace ${workspaceId}`
);
}
private async ensureWorkspaceContentExists(workspaceId: string) {
await this.docReader.getWorkspaceContent(workspaceId);
}
async markAsRead(userId: string, notificationId: string) {
try {
await this.models.notification.markAsRead(notificationId, userId);
} catch (err) {
if (
err instanceof Prisma.PrismaClientKnownRequestError &&
err.code === 'P2025'
) {
// https://www.prisma.io/docs/orm/reference/error-reference#p2025
throw new NotificationNotFound();
}
throw err;
}
await this.publishCountChanged(userId, 'read');
}
async markAllAsRead(userId: string) {
await this.models.notification.markAllAsRead(userId);
await this.publishCountChanged(userId, 'read-all');
}
/**
* Find notifications by user id, order by createdAt desc
*/
async findManyByUserId(userId: string, options?: PaginationInput) {
const notifications = await this.models.notification.findManyByUserId(
userId,
optionsView on GitHub (pinned to 26c515e050)
Solutions
- Treat code=notification_not_found as idempotent success on the client (the end state — notification read/gone — is achieved) rather than an error.
- Prune local notification lists when a clear-all or bulk action happens to avoid stale ids.
- Have markAsRead return void/no-op on not-found instead of throwing if idempotency is desired.
- Verify the notificationId shape before submitting to catch obvious client corruption.
Example fix
// before — throws on already-deleted notification
await this.models.notification.markAsRead(notificationId, userId);
// after — treat P2025 as success (already in desired state)
async markAsRead(userId, notificationId) {
try {
await this.models.notification.markAsRead(notificationId, userId);
} catch (err) {
if (err instanceof Prisma.PrismaClientKnownRequestError && err.code === 'P2025') {
return; // notification already gone — nothing to mark
}
throw err;
}
await this.publishCountChanged(userId, 'read');
} Defensive patterns
Strategy: try-catch
Validate before calling
function assertNotificationId(id: string) {
if (!/^[0-9a-f-]{16,}$/i.test(id)) throw new UserError('Invalid notification id');
}
// Best prevention: treat not-found as idempotent success on the client. Type guard
function isNotificationNotFound(e: unknown): boolean {
return e instanceof Error && (e as any).code === 'notification_not_found';
} Try / catch
try {
await service.markAsRead(me.id, notificationId);
} catch (e) {
if (isNotificationNotFound(e)) {
// already gone — desired state achieved
return;
}
throw e;
} Prevention
- Treat notification_not_found as idempotent success, not an error to show.
- Prune local notification ids after clear-all / bulk actions.
- Validate notification id shape before submitting.
- Consider making markAsRead no-op on P2025 server-side.
When it happens
Trigger: Client calls markAsRead with a notificationId that doesn't exist, belongs to another user, or was already deleted. Race with a delete/clear-all. Id from a stale push payload.
Common situations: Stale notification center UI holding ids for notifications cleared on another device. Web push with an old id after the user cleared all. Notification expired/archived between delivery and read.
Related errors
- Can not find the version to rollback to.
- Workspace ${workspaceId} not found or has no root document
- Document ${docId} not found
- mention_user_oneself_denied
- Failed to read image size
AI-assisted analysis of toeverything/AFFiNE@26c515e050 (2026-08-12).
Data as JSON: /api/errors/cd862196fd0184d0.
Report an issue: GitHub.