From a1cb2db1907313530b50798dea0e37278cbbb0ef Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Sat, 7 Nov 2026 22:17:52 -0700 Subject: A Lightning receive steps past a payment hash the server says was canceled, as it already did for one paid or merely issued. Claiming Adam's own withdraw link (2026-11-08) failed before the claim was sent: "StartLightningReceive: bad user input: the invoice for payment hash c2d7… was canceled" — the preimage counter was sitting on an index whose invoice an earlier cancel retired (another device's, or a state that hadn't heard), and createLnInvoice only treated "already been paid" / UNIQUE constraint answers as spoken-for, so it threw instead of taking the next index. Matched on the server's wording ("payment hash was canceled"), not a bare "cancelled", so an aborted request still fails as itself MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01VMan6Ts5Tktega8VbLg31q --- src/ark/manager.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ark/manager.js b/src/ark/manager.js index 91b5f0a..0370a77 100644 --- a/src/ark/manager.js +++ b/src/ark/manager.js @@ -1870,9 +1870,11 @@ export class ArkManager { }); } catch (e) { // "already been paid" for a settled one; "UNIQUE constraint failed: - // invoices.payment_hash" for one merely issued before — both mean - // this index is spoken for - const used = /already been paid|already exists|already in use|duplicate|UNIQUE constraint|payment_hash/i.test(e?.message || ''); + // invoices.payment_hash" for one merely issued before; "the invoice + // for payment hash … was canceled" for one a cancel retired (a + // withdraw-link claim died on that, 2026-11-08) — all mean this + // index is spoken for + const used = /already been paid|already exists|already in use|duplicate|UNIQUE constraint|payment_hash|payment hash [0-9a-f]+ was cancel+ed/i.test(e?.message || ''); if (!used || tries >= 200) throw e; this._save(); // remember the skipped index even if the next try fails continue; -- cgit v1.2.3