louislam/uptime-kuma · error · Error
Error decoding recipient ${recipient}: ${error}
Error message
Error decoding recipient ${recipient}: ${error} What it means
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.
Source
Thrown at server/notification-providers/nostr.js:108
/**
* Get public keys for recipients
* @param {string} recipients Newline delimited list of recipients
* @returns {Promise<nip19.DecodeResult[]>} Public keys
*/
async getPublicKeys(recipients) {
const recipientsList = recipients.split("\n");
const publicKeys = [];
for (const recipient of recipientsList) {
try {
const recipientDecodeResult = await nip19.decode(recipient);
const { type, data } = recipientDecodeResult;
if (type === "npub") {
publicKeys.push(data);
} else {
throw new Error(`Recipient ${recipient} is not an npub`);
}
} catch (error) {
throw new Error(`Error decoding recipient ${recipient}: ${error}`);
}
}
return publicKeys;
}
}
module.exports = Nostr;
View on GitHub (pinned to 6b5ea01557)
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.
Example fix
// before
} catch (error) {
throw new Error(`Error decoding recipient ${recipient}: ${error}`);
}
// after - cleaner message and skip blanks upstream
} catch (error) {
throw new Error(`Error decoding recipient ${recipient}: ${error.message}`);
} Defensive patterns
Strategy: try-catch
Validate before calling
const recipientsList = recipients.split("\n").map(s => s.trim()).filter(Boolean); Try / catch
for (const recipient of recipientsList) {
try {
const { type, data } = await nip19.decode(recipient);
if (type !== "npub") throw new Error(`not an npub (got ${type})`);
publicKeys.push(data);
} catch (error) {
throw new Error(`Cannot decode recipient '${recipient}': ${error.message}`);
}
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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).
Related errors
- Failed to decode private key for sender ${sender}: ${error.m
- Recipient ${recipient} is not an npub
- ${error.response.data ? error.response.data : "Error without
- Failed to create gift-wrapped event for recipient: ${error.m
- ${msg}
AI-assisted analysis of louislam/uptime-kuma@6b5ea01557 (2026-08-12).
Data as JSON: /api/errors/b00ca5b40f114dab.
Report an issue: GitHub.