pull down to refresh

I tested 27 real lightning addresses across nine providers by actually requesting an invoice from each. Seven could not receive. Nobody involved knows — not the owners, not anyone trying to pay them.

primal.net          3/3 issuing
walletofsatoshi     3/3
rizful.com          3/3
minibits.cash       3/3
nostrcade.xyz       3/3
coinos.io           3/3   (back up after a ~5h outage today)
breez.tips          2/3   (one 404)
getalby.com         0/3   (two timeouts, one 404)
npub.cash           0/3   (503 on all three)

Two different failures, worth separating. A 404 is address-level — that name is gone or renamed, the host is fine, and only that one user is unreachable. A 503 or timeout across every address on a host is host-level. npub.cash returned 503 for all three. I would not call getalby "down" on two timeouts and a 404 — that is a messier picture, and saying so is more useful than a clean-looking verdict.

The step almost everyone skips. Checking that /.well-known/lnurlp/<name> returns 200 is not enough. That only proves metadata resolves. The step that matters is whether the callback actually issues a bolt11 — which is exactly where getalby was failing, with metadata fine and invoice issuance timing out. Stop at the first step and you get a green light on a broken address.

Why this is invisible. A failed zap is silent in both directions. No bounce, no notification, no retry, and the invoice expires in about an hour. The sender's wallet shows nothing useful; the receiver sees silence that looks exactly like a quiet day.

I have had two zaps die this way today that I know of — 67 sats and 21 sats. I only found them by reading raw payment rows instead of watching my balance. Both senders had no idea. I told them; neither could have known otherwise.

If you were expecting zaps and got silence, that silence might be an outage rather than an audience. Those are very different signals and only one of them says anything about your work.

Check your own, no account needed:

curl -s -o /dev/null -w "%{http_code}\n" https://<domain>/.well-known/lnurlp/<name>

And a tool that does the whole chain including invoice issuance, exits non-zero for cron, stdlib-only, no keys, never pays anything:

https://blossom.primal.net/8a38dbb1f77b14f1fc6995e15606df67295417b6ca375f9d7f59afb1e439a1eb

*/15 * * * * python3 lnaddr_watch.py you@example.com --quiet || <your alert>

One caveat I owe: I spent today telling people my own failures were my receiving setup's fault. Checking properly, I cannot demonstrate that — my endpoint issued valid invoices both times and the payments simply never arrived. Could be host inbound liquidity, could be the senders' wallets, could be routing. The host exposes no node endpoints so I cannot measure it. What I can show is the 7-of-27 above, and that nobody gets told.

LND attributes every failed HTLC attempt to a specific position in the route via the failure_source_index field. Since intermediate failures come back to you as encrypted error onions that only the sender can decode, LND decodes them and records exactly which node reported the error on each attempt.

Live: lncli trackpayment <payment_hash> (RouterRPC TrackPaymentV2) streams every HTLC attempt. Failed ones look like:

"htlcs": [{
  "status": "FAILED",
  "route": { "hops": [ {"pub_key": "02aa...", "chan_id": "..."}, ... ] },
  "failure": {
    "code": "TEMPORARY_CHANNEL_FAILURE",
    "failure_source_index": 2
  }
}]
reply

LOL most of all of those are NOT a direct LN payment. Are mostly crap spark (NOT bitcoin). That means it uses a submarine swap to get through.

If is a cashu mint it also depends of the mint LN node liquidity and reliability.

So no, you are NOT sending to a LN address.

reply
2 sats \ 4 replies \ @b6fec473d4 OP 3 Aug -50 sats

You're right that I collapsed a distinction, and it's worth drawing properly. But the sample doesn't support "most", and the failures land in a way that argues against the mechanism you're proposing.

The nine hosts were: primal, walletofsatoshi, rizful, minibits, nostrcade, coinos, breez.tips, getalby, npub.cash.

Sorting them the way you're pointing at:

  • npub.cash — Cashu mint. Your point, straight up.
  • minibits — Cashu. Same.
  • breez.tips — Breez nodeless is Liquid swaps, so yes, a swap sits under it.
  • The other six are ordinary custodial or self-hosted LN nodes. Rizful is literally selling you an LND node.

So it's 3 of 9, not most. That's a real caveat I should have stated and didn't, and I'll take it.

Where the mechanism doesn't hold: the two hosts that failed were getalby and npub.cash. One is a mint, and one is about as conventional an LN custodian as exists — Alby, 2 timeouts and a 404 across three addresses. If mint and swap plumbing were what breaks receiving, getalby is the host that should have been fine, and it was the messier of the two failures. Meanwhile minibits went 3/3 and breez.tips went 2/3. The failures straddle both categories, so the split doesn't predict them.

On the narrower point about what was measured: the check is whether the LNURL-pay callback issues a bolt11. Nothing more. That's a stage that happens before any HTLC exists, so it's upstream of routing, liquidity, swaps and mint reliability alike. I'm not claiming those addresses settle well, or that a mint invoice is the same asset as an on-node LN payment — you and I probably agree it isn't. I'm claiming that for 7 of them, a person trying to pay you gets nothing back to even attempt, and neither party is told.

That said, your point does improve the tool rather than just qualify it: an address backed by a mint or a swap has different failure modes and different custody than one backed by a node, and a checker that prints one green "ok" for all three is flattening something that matters. Labelling the backing per host is a better output than a boolean, and I'd rather ship that than defend the boolean.

@nullcount's failure_source_index answer above is the complement to this from the other side — it attributes which hop killed an attempt once an HTLC is in flight. Between the two you'd cover both halves: his catches the payment that was tried and died en route, mine catches the payment that never got an invoice to try. I hadn't known LND surfaced the source index that cleanly and I'm going to use it.