{"record":{"id":"9807e2832683618c","repo":"louislam/uptime-kuma","slug":"recipient-recipient-is-not-an-npub","errorCode":null,"errorMessage":"Recipient ${recipient} is not an npub","messagePattern":"Recipient (.+?) is not an npub","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"server/notification-providers/nostr.js","lineNumber":105,"sourceCode":"        }\n    }\n\n    /**\n     * Get public keys for recipients\n     * @param {string} recipients Newline delimited list of recipients\n     * @returns {Promise<nip19.DecodeResult[]>} Public keys\n     */\n    async getPublicKeys(recipients) {\n        const recipientsList = recipients.split(\"\\n\");\n        const publicKeys = [];\n        for (const recipient of recipientsList) {\n            try {\n                const recipientDecodeResult = await nip19.decode(recipient);\n                const { type, data } = recipientDecodeResult;\n                if (type === \"npub\") {\n                    publicKeys.push(data);\n                } else {\n                    throw new Error(`Recipient ${recipient} is not an npub`);\n                }\n            } catch (error) {\n                throw new Error(`Error decoding recipient ${recipient}: ${error}`);\n            }\n        }\n        return publicKeys;\n    }\n}\n\nmodule.exports = Nostr;\n","sourceCodeStart":87,"sourceCodeEnd":116,"githubUrl":"https://github.com/louislam/uptime-kuma/blob/6b5ea0155793e666666745fb8d6fef1e829543a2/server/notification-providers/nostr.js#L87-L116","documentation":"Inside Nostr.getPublicKeys, each recipient is decoded with nip19.decode; if decoding succeeds but the result type is not 'npub' (for example it is an nsec, note, nprofile, or nrelay), this Error is thrown. It is immediately caught by the surrounding per-recipient catch (line 107) and re-wrapped as 'Error decoding recipient <recipient>: <error>', so in practice the outer message is what surfaces.","triggerScenarios":"A recipient entry is a valid bech32 entity but the wrong kind: an nsec1 (private key) instead of npub1, an nprofile1, a note1 event id, or any other NIP-19 entity that decodes but is not a public key.","commonSituations":"User pasted their own private key (nsec) into the recipient list; pasted a profile/event id; mixed up public and private key fields when distributing recipients.","solutions":["Collect recipient addresses as npub1... strings only (public keys).","Strip empty lines and trim each line in the recipients list before decoding.","If you only have hex public keys, convert them to npub with nip19.npubEncode before saving.","Treat the surfaced 'Error decoding recipient' as pointing at the specific offending entry."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"for (const r of recipientsList) {\n    const t = r.trim();\n    if (!t) continue;\n    if (!t.startsWith(\"npub1\")) {\n        throw new Error(`Recipient '${t}' is not an npub1... public key`);\n    }\n}","typeGuard":"/** @param {string} s */\nfunction looksLikeNpub(s) {\n    return typeof s === \"string\" && s.startsWith(\"npub1\") && s.length > 10;\n}","tryCatchPattern":null,"preventionTips":["Filter blank lines before decoding recipients.","Validate npub1 prefix before invoking nip19.decode.","Keep private (nsec) values out of the recipient list."],"tags":["nostr","nip19","npub","validation","key-format"],"backgroundTag":null,"analyzedSha":"6b5ea0155793e666666745fb8d6fef1e829543a2","analyzedAt":"2026-08-12T23:42:12.959Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}