{"record":{"id":"b00ca5b40f114dab","repo":"louislam/uptime-kuma","slug":"error-decoding-recipient-recipient-error","errorCode":null,"errorMessage":"Error decoding recipient ${recipient}: ${error}","messagePattern":"Error decoding recipient (.+?): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/notification-providers/nostr.js","lineNumber":108,"sourceCode":"    /**\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":90,"sourceCodeEnd":116,"githubUrl":"https://github.com/louislam/uptime-kuma/blob/6b5ea0155793e666666745fb8d6fef1e829543a2/server/notification-providers/nostr.js#L90-L116","documentation":"The outer catch in Nostr.getPublicKeys wraps any per-recipient failure (a thrown decode error from nip19.decode, or the inner 'is not an npub' throw) as 'Error decoding recipient <recipient>: <error>'. Because it interpolates the whole error object (not error.message), the surfaced text may include the Error's string representation, sometimes twice-nested.","triggerScenarios":"Any recipient line that fails nip19.decode (invalid bech32, bad checksum, unrecognised prefix) or that decodes to a non-npub type. The inner throw at line 105 also lands here.","commonSituations":"A blank/whitespace line in the recipients textarea; a recipient copied with extra characters; an npub from a different bech32 convention; line-ending artifacts from copy/paste (CRLF).","solutions":["Inspect the recipient token named in the message and fix or remove it.","Pre-filter the recipient list: split on newline, trim, drop empty lines before decoding.","Interpolate error.message instead of error to keep the surfaced message concise and non-redundant.","Validate each entry starts with 'npub1' before attempting nip19.decode."],"exampleFix":"// before\n} catch (error) {\n    throw new Error(`Error decoding recipient ${recipient}: ${error}`);\n}\n\n// after - cleaner message and skip blanks upstream\n} catch (error) {\n    throw new Error(`Error decoding recipient ${recipient}: ${error.message}`);\n}","handlingStrategy":"try-catch","validationCode":"const recipientsList = recipients.split(\"\\n\").map(s => s.trim()).filter(Boolean);","typeGuard":null,"tryCatchPattern":"for (const recipient of recipientsList) {\n    try {\n        const { type, data } = await nip19.decode(recipient);\n        if (type !== \"npub\") throw new Error(`not an npub (got ${type})`);\n        publicKeys.push(data);\n    } catch (error) {\n        throw new Error(`Cannot decode recipient '${recipient}': ${error.message}`);\n    }\n}","preventionTips":["Interpolate error.message (not the whole error) to avoid nested/redundant text.","Trim and drop empty recipient lines before decoding.","Report the offending entry to the user clearly."],"tags":["nostr","nip19","error-handling","recipient"],"backgroundTag":null,"analyzedSha":"6b5ea0155793e666666745fb8d6fef1e829543a2","analyzedAt":"2026-08-12T23:42:12.959Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}