Skip to content

NIP-57 receipt worker crashes (receipt silently lost) when the zap request has no relays tag #3218

Description

@singap2002-code

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

worker/nostr.js (nip57) extracts the relay list from the zap request like this:

const relays = note.tags.find(t => t?.length >= 2 && t[0] === 'relays').slice(1)

If the zap request note has no relays tag, find returns undefined and .slice(1) throws TypeError: Cannot read properties of undefined (reading 'slice'). The throw is inside the try/catch, so it is swallowed as a logged failed to publish NIP-57 receipt: error and the zap receipt (kind 9735) is never published — even though the payer already paid the invoice.

The problem is that such a note can reach the worker: the NIP-57 validation in pages/api/lnurlp/[username]/pay.js only checks the signature, the p tag count, the e tag count and the optional amount tag — it does not require a relays tag. NIP-57 Appendix D also phrases it loosely ("There should be a relays tag"), so third-party wallets are allowed to omit it. The invoice is created with the zap request's description hash, the payment settles, nip57 is queued, and the receipt is silently lost.

Minimal repro of the crash (node):

const note = { pubkey: 'ab'.repeat(32), tags: [['p','cd'.repeat(32)],['amount','21000']] }
note.tags.find(t => t?.length >= 2 && t[0] === 'relays').slice(1)
// TypeError: Cannot read properties of undefined (reading 'slice')

This affects both the proxied path (payInBolt11.nostrNote) and the new direct-receive path (externalTransaction.nostrNote) added in ca3b05e.

Steps To Reproduce

  1. Send a zap to a user@stacker.news lightning address with a signed NIP-57 zap request that has valid p/amount tags but no relays tag (some wallets/clients omit it).
  2. pay.js accepts the note (validation passes), returns a description-hash invoice.
  3. Pay the invoice.
  4. The nip57 boss job runs and throws on the relay extraction; the receipt is never published and the zap sender's client never sees a zap receipt for a payment that succeeded.

Expected behavior

Either:

  • reject zap requests without a relays tag during validation in pay.js (fail fast with invalid NIP-57 note, so the payer knows before paying), or
  • make the worker defensive, e.g. const relays = note.tags.find(...)?.slice(1) ?? DEFAULT_CROSSPOSTING_RELAYS so the receipt still gets published to sensible default relays.

Logs

failed to publish NIP-57 receipt: TypeError: Cannot read properties of undefined (reading 'slice')

Device information

  • N/A (server-side worker)

Additional context

Found while reading the wallet/nostr changes from ca3b05e ("wallets: support configurable direct and proxied receives"). I can submit a small draft PR with either fix if the maintainers prefer one direction.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions