diff --git a/extensions/discord/src/send.reactions.ts b/extensions/discord/src/send.reactions.ts index 0eb49cd849e3..4c2465d8715a 100644 --- a/extensions/discord/src/send.reactions.ts +++ b/extensions/discord/src/send.reactions.ts @@ -87,17 +87,13 @@ export async function removeOwnReactionsDiscord( if (identifiers.size === 0) { return { ok: true, removed: [] }; } - const removed: string[] = []; - await Promise.allSettled( - Array.from(identifiers, (identifier) => { - removed.push(identifier); - return deleteOwnMessageReaction( - rest, - channelId, - messageId, - normalizeReactionEmoji(identifier), - ); - }), + const removed = Array.from(identifiers); + // Promise.all so a rejected delete propagates: allSettled would swallow the + // failure and falsely report every identifier as removed. + await Promise.all( + removed.map((identifier) => + deleteOwnMessageReaction(rest, channelId, messageId, normalizeReactionEmoji(identifier)), + ), ); return { ok: true, removed }; } diff --git a/extensions/discord/src/send.sends-basic-channel-messages.test.ts b/extensions/discord/src/send.sends-basic-channel-messages.test.ts index debebb466537..638456c4ccf4 100644 --- a/extensions/discord/src/send.sends-basic-channel-messages.test.ts +++ b/extensions/discord/src/send.sends-basic-channel-messages.test.ts @@ -861,6 +861,24 @@ describe("removeOwnReactionsDiscord", () => { Routes.channelMessageOwnReaction("chan1", "msg1", "party_blob%3A123"), ); }); + + it("surfaces a failed deletion instead of reporting false success", async () => { + const { rest, getMock, deleteMock } = makeDiscordRest(); + getMock.mockResolvedValue({ + reactions: [ + { emoji: { name: "✅", id: null } }, + { emoji: { name: "party_blob", id: "123" } }, + ], + }); + const apiError = new Error("Discord API 500"); + deleteMock.mockResolvedValueOnce(undefined); + deleteMock.mockRejectedValueOnce(apiError); + await expect( + removeOwnReactionsDiscord("chan1", "msg1", { rest, token: "t", cfg: DISCORD_TEST_CFG }), + ).rejects.toThrow("Discord API 500"); + // Both deletions are still attempted; the rejection just propagates. + expect(deleteMock).toHaveBeenCalledTimes(2); + }); }); describe("fetchReactionsDiscord", () => {