louislam/uptime-kuma · error · Error
notification not found
Error message
notification not found
What it means
Thrown by Notification.save during an update (notificationID provided) when no notification row matches both the given id AND the user_id. The AND user_id clause enforces ownership: a missing row means either the id does not exist or it belongs to a different user.
Source
Thrown at server/notification.js:272
throw new Error("Notification type is not supported");
}
}
/**
* Save a notification
* @param {object} notification Notification to save
* @param {?number} notificationID ID of notification to update
* @param {number} userID ID of user who adds notification
* @returns {Promise<Bean>} Notification that was saved
*/
static async save(notification, notificationID, userID) {
let bean;
if (notificationID) {
bean = await R.findOne("notification", " id = ? AND user_id = ? ", [notificationID, userID]);
if (!bean) {
throw new Error("notification not found");
}
} else {
bean = R.dispense("notification");
}
// applyExisting is one time only, don't save it to database.
const applyExisting = notification.applyExisting || false;
notification.applyExisting = false;
bean.name = notification.name;
bean.user_id = userID;
bean.config = JSON.stringify(notification);
bean.is_default = notification.isDefault || false;
await R.store(bean);
if (applyExisting) {
await applyNotificationEveryMonitor(bean.id, userID);
}View on GitHub (pinned to 6b5ea01557)
Solutions
- Refresh the notifications list in the UI to discard stale ids and retry the edit.
- Confirm the authenticated user actually owns the notification (check user_id in the DB row).
- If the notification was deleted intentionally, create a new one instead of updating the old id.
- Inspect server logs to confirm the (notificationID, userID) pair being passed.
Defensive patterns
Strategy: validation
Validate before calling
// Verify ownership before attempting an update
async function notificationExistsForUser(notificationID, userID) {
const bean = await R.findOne("notification", " id = ? AND user_id = ? ", [notificationID, userID]);
return bean != null;
}
if (notificationID && !(await notificationExistsForUser(notificationID, userID))) {
throw new Error("notification not found");
} Type guard
/** True when a bean was found for the (id, user) pair. */
function isOwnedNotification(bean) { return bean != null; } Try / catch
try {
const bean = await R.findOne("notification", " id = ? AND user_id = ? ", [notificationID, userID]);
if (!bean) throw new Error("notification not found");
// ...proceed with update
} catch (err) { throw err; } Prevention
- Refresh the notifications list before editing to drop stale ids.
- Confirm the logged-in user owns the target notification.
- Avoid concurrent edits across tabs.
When it happens
Trigger: Editing a notification whose id was already deleted, a stale id held in the browser after another session deleted it, or a user_id mismatch (wrong user editing another's notification, possibly via a tampered request).
Common situations: Two browser tabs open: one deletes the notification while the other tries to save; client-side id caching after deletion; or privilege escalation attempt via crafted notificationID.
Related errors
- proxy not found
- Remote browser not found
- Remote Browser not found
- docker host not found
- Child monitors down: ${downChildren.join(", ")}; pending: ${
AI-assisted analysis of louislam/uptime-kuma@6b5ea01557 (2026-08-12).
Data as JSON: /api/errors/987c289a63031724.
Report an issue: GitHub.