utilities icon indicating copy to clipboard operation
utilities copied to clipboard

bug: Upgrading discordjs-utilities to 7.3.1 causing the process to crash

Open KagChi opened this issue 1 year ago • 9 comments

Is there an existing issue for this?

  • [X] I have searched the existing issues

Description of the bug

I recently upgraded to 7.3.1 and this causing to crash on missing perms


node:internal/event_target:1090
  process.nextTick(() => { throw err; });
                           ^
DiscordAPIError[50001]: Missing Access
    at handleErrors (/app/node_modules/.pnpm/@[email protected]/node_modules/@discordjs/rest/dist/index.js:727:13)
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
    at async SequentialHandler.runRequest (/app/node_modules/.pnpm/@[email protected]/node_modules/@discordjs/rest/dist/index.js:1128:23)
    at async SequentialHandler.queueRequest (/app/node_modules/.pnpm/@[email protected]/node_modules/@discordjs/rest/dist/index.js:959:14)
    at async _REST.request (/app/node_modules/.pnpm/@[email protected]/node_modules/@discordjs/rest/dist/index.js:1272:22)
    at async GuildMessageManager.edit (/app/node_modules/.pnpm/[email protected]/node_modules/discord.js/src/managers/MessageManager.js:188:15)
    at async safelyReplyToInteraction (file:///app/node_modules/.pnpm/@[email protected]/node_modules/@sapphire/discord.js-utilities/dist/esm/index.mjs:699:5) {
  requestBody: {
    files: [],
    json: {
      content: undefined,
      tts: false,
      nonce: undefined,
      enforce_nonce: false,
      embeds: undefined,
      components: [],
      username: undefined,
      avatar_url: undefined,
      allowed_mentions: undefined,
      flags: 0,
      message_reference: undefined,
      attachments: undefined,
      sticker_ids: undefined,
      thread_name: undefined,
      applied_tags: undefined,
      poll: undefined
    }
  },
  rawError: { message: 'Missing Access', code: 50001 },
  code: 50001,
  status: 403,
  method: 'PATCH',
  url: 'http://nirn.production.svc.cluster.local:6070/api/v10/channels/635490854089261077/messages/1312765356749750336'
}

Steps To Reproduce

Use 7.3.1 and run PaginationMessage on missing perms channel.

Expected behavior

Promise should be handled correctly

Screenshots

No response

Additional context

No response

System Info

<i cant run inside k3s container>

KagChi avatar Dec 01 '24 13:12 KagChi

Let me guess, your installed the bot as a user application and used the command in a server where the bot is not a member and/or doesn't have the Read Message History permission? There is a known bug with user installed apps.

favna avatar Dec 01 '24 23:12 favna

Let me guess, your installed the bot as a user application and used the command in a server where the bot is not a member and/or doesn't have the Read Message History permission? There is a known bug with user installed apps.

The bot are not user installed apps as im aware. im sure i only enabled guild install.

KagChi avatar Dec 04 '24 00:12 KagChi

In that case we need much more information.

  • What perms are missing
  • what is the command code
  • is this a slash command or message command, on that note, are you using @sapphire/framework or not?

Just this error really doesn't say much to us

favna avatar Dec 04 '24 00:12 favna

In that case we need much more information.

  • What perms are missing
  • what is the command code
  • is this a slash command or message command, on that note, are you using @sapphire/framework or not?

Just this error really doesn't say much to us

permissions missing should not make the process crashed? here is the command https://bin.hzmi.xyz/opidaxeceg.typescript that is a slash command, and yeah i did use @sappphire/framework

KagChi avatar Dec 04 '24 01:12 KagChi

Looking at the error stacktrace more carefully the error comes from safelyReplyToInteraction which is on line 699 of index.mjs which notably is the code not for interactions but for regular messages image

There are a few things that can be said about this:

  1. This code hasn't changed between 7.3.0 and 7.3.1
  2. Under normal circumstances there is no way that this check between interaction and regular message should fail: https://github.com/sapphiredev/utilities/blob/main/packages/discord.js-utilities/src/lib/type-guards.ts#L290-L298

As stated.. under normal circumstances. This is a subjective take but IMHO your code is a mess and it took me a good 15 minutes and copying it to VSCode to get bracket pair colourizing to understand what was even happening. Setting aside my personal bias against premium features on a bot, I suspect it might be related to the setTimeout function where you're spamming users about your premium features and the asynchronous followUp causing the interaction to get wacky. Nothing else would ever be able to make the interaction not be an instanceof BaseInteraction. Lastly what I can also conclude from the JSON body that is being attempted to be PATCHed is that it's from this safelyReplyToInteraction specifically: https://github.com/sapphiredev/utilities/blob/main/packages/discord.js-utilities/src/lib/PaginatedMessages/PaginatedMessage.ts#L1655-L1662, so that is the method that is called when the PaginatedMessage stops, either through time elapse, by clicking the stop button, or by the same user using another command that gives another paginatedmessage. What I suspect may be happening is that this.response.fetchReply() gets the followed up message rather than the actual message.

Hopefully you can get somewhere with this information. I sincerely think it isn't in the library's code itself and short of the DiscordJS update of 7.3.1 you could also get this issue in earlier versions.

As for this:

permissions missing should not make the process crashed?

No, they shouldn't, but only if you yourself handle your own errors correctly. You can find out more here: https://discordjs.guide/popular-topics/errors.html#how-to-diagnose-api-errors

favna avatar Dec 06 '24 02:12 favna

Thank you for the clarifications, i appreciate your hard work and for great utilities for the DJS communities. but the snippet code you sent

if (this.response && !PaginatedMessage.deletionStopReasons.includes(reason)) {
	void safelyReplyToInteraction({
		messageOrInteraction: this.response,
		interactionEditReplyContent: { components: [] },
		interactionReplyContent: { ...this.#thisMazeWasNotMeantForYouContent, ephemeral: true },
		componentUpdateContent: { components: [] },
		messageMethod: 'edit',
		messageMethodContent: { components: [] }
	});
}

Could be the problems. and can the error handled correctly?

KagChi avatar Dec 06 '24 02:12 KagChi

I would be willing to add an error handler but to do so I would need to reproduce the error locally first. If you can provide a small repository where the issue can be reproduced that would go a very long way.

favna avatar Dec 06 '24 08:12 favna

Sorry for late replies. i cannot create any minimal reproduce repo for you test right now. but i managed to suspend the crash issues by extending the PaginatedMessage. so it is the issue of handleEnd

import type { PaginatedMessageInteractionUnion, PaginatedMessageStopReasons } from "@sapphire/discord.js-utilities";
import { isAnyInteraction, PaginatedMessage, safelyReplyToInteraction } from "@sapphire/discord.js-utilities";
import type { Collection, Snowflake } from "discord.js";

export class NezuPaginatedMessage extends PaginatedMessage {
    readonly #thisMazeWasNotMeantForYouContent = { content: "This maze wasn't meant for you...what did you do." };

    protected async handleEnd(_: Collection<Snowflake, PaginatedMessageInteractionUnion>, reason: PaginatedMessageStopReasons): Promise<void> {
        if (
            (reason === "time" || reason === "idle") &&
            this.response !== null &&
            isAnyInteraction(this.response) &&
            this.response.isMessageComponent()
        ) {
            try {
                this.response.message = await this.response.fetchReply();
            } catch { /*  */ }
        }

        this.collector?.removeAllListeners();

        if (this.response && !PaginatedMessage.deletionStopReasons.includes(reason)) {
            try {
                await safelyReplyToInteraction({
                    messageOrInteraction: this.response,
                    interactionEditReplyContent: { components: [] },
                    interactionReplyContent: { ...this.#thisMazeWasNotMeantForYouContent, ephemeral: true },
                    componentUpdateContent: { components: [] },
                    messageMethod: "edit",
                    messageMethodContent: { components: [] }
                });
            } catch { /* */ }
        }
    }
}

KagChi avatar Dec 11 '24 11:12 KagChi

I already knew the problem was with handleEnd, but by all logic of the code it should never happen, which is why I need a reproduction sample so I can probably debug the issue and solve it.

favna avatar Dec 12 '24 10:12 favna