From 917633aeeab8518af9e52a16532d8485dbd62e2a Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Sat, 5 Sep 2026 00:35:17 -0700 Subject: credit: skip settlements for a deleted account instead of throwing getUser(inv.uid) returns nothing when the account was deleted but its invoice or bolt12 offer still receives (OCEAN payouts to a deleted user's offer). The destructure on the next line threw inside the lightning listener, which never advanced pay_index and crash-looped the app every 50s, blocking all incoming lightning for two hours. Record the preimage in `missing` and return, as an unknown invoice already does. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01VMi2Y1oKPZ3TeeFmLej47y --- lib/payments.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'lib') diff --git a/lib/payments.ts b/lib/payments.ts index eba60eb0..b26b443f 100644 --- a/lib/payments.ts +++ b/lib/payments.ts @@ -385,6 +385,16 @@ export const credit = async ({ if (type === PaymentType.internal) amount += tip; const user = await getUser(inv.uid); + if (!user) { + // The account is gone (deleted) but its invoice still receives — e.g. a + // bolt12 offer a mining pool keeps paying. Record the settlement in + // `missing` and skip, like an unknown invoice. Throwing here wedged the + // lightning listener on one settlement and blocked every later receipt + // for two hours (2026-09-05, pay_index 1068006). + warn("received payment for missing user", inv.uid, hash, amount); + await db.sAdd("missing", ref.split(":")[0]); + return; + } const { id: uid, currency } = user; const rates = await g("rates"); -- cgit v1.2.3