HeyPuter/puter · error · HttpError

not_found

not_found

Error message

Notification not found

What it means

NotificationDriver.read() resolved the uid but no notification row exists for that uid owned by the calling user (the lookup is scoped by actor.user.id). This is an owner-scoped 404 — the notification either does not exist, was deleted, or belongs to a different user.

Source

Thrown at src/backend/drivers/notification/NotificationDriver.ts:115

            userId: actor.user.id,
            value,
        });
        return this.#toClient(created);
    }

    async read(args: Record<string, unknown>): Promise<unknown> {
        const actor = this.#requireUserActor();
        const uid = (args.uid ?? args.id) as string | undefined;
        if (!uid)
            throw new HttpError(400, 'Missing `uid`', {
                legacyCode: 'bad_request',
            });

        const row = await this.stores.notification.getByUid(String(uid), {
            userId: actor.user.id,
        });
        if (!row)
            throw new HttpError(404, 'Notification not found', {
                legacyCode: 'not_found',
            });
        return this.#toClient(row);
    }

    async select(args: Record<string, unknown>): Promise<unknown[]> {
        const actor = this.#requireUserActor();
        const limit = Math.min(
            Number(args.limit ?? MAX_SELECT_LIMIT),
            MAX_SELECT_LIMIT,
        );
        const predicate = args.predicate as string | string[] | undefined;

        const predicateName = Array.isArray(predicate)
            ? predicate[0]
            : predicate;

        // Route predicate → store query params

View on GitHub (pinned to 908ec23eda)

Solutions

  1. Verify the uid is from the current user's own notification list (e.g. from select).
  2. Treat a 404 as 'already gone' and clear it from the UI rather than retrying.
  3. Refresh the notification list to get live uids.

Example fix

// before
const n = await notifications.read({ uid: staleUid });

// after
try {
  const n = await notifications.read({ uid: notif.uid });
} catch (e) {
  if (e.code === 'not_found') { /* drop from UI */ }
  else throw e;
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const n = await notifications.read({ uid });
} catch (e) {
  if (e.status === 404 && e.code === 'not_found') {
    // already gone — remove from UI, do not retry
  } else throw e;
}

Prevention

When it happens

Trigger: Passing a uid that was never created; a uid from another user's notification list; a uid of an already-deleted notification; a malformed uid that simply does not match.

Common situations: Stale uid cached in the UI after the notification was acknowledged/cleared; cross-user uid leak; test using a uid from a different account; uid truncated/corrupted in transit.

Related errors


AI-assisted analysis of HeyPuter/puter@908ec23eda (2026-08-12). Data as JSON: /api/errors/a5d76d00099a4cda. Report an issue: GitHub.