Creating a custom UserError

I want to use a custom UserError to create preconditions for my subcommands. I can't find any documentation examples on it. Anyone have any suggestions so that in my custom preconditions class I can call throw new UserError and have it go to my custom function?
15 Replies
Favna
Favna12mo ago
you pretty much have to use this.error for it to work. Why do you want to use a custom class? I don't see any particular reason for it. If you want to pass additional data you do that through the context key.
rhh4x0R
rhh4x0R12mo ago
Ah ok. I was just reading in another thread that there aren't preconditions that exist with Subcommands so we have to build our own. Maybe I misunderstood.
Favna
Favna12mo ago
oh I missed that part. No that is correct, there arent any. but any custom precondition is still going to have to be called from within the subcommand and is still going to end up in the subcommand error specific listeners simply because they're not really preconditions, they're just if checks to understand this better you need to understand the Sapphire code for running preconditions which is https://github.com/sapphiredev/framework/blob/main/src/listeners/application-commands/chat-input/CorePreChatInputCommandRun.ts as you can see here, before we even consider running the chatInputRun method we already run the preconditions however for resolving subcommands we hook into that same chatInputRun: https://github.com/sapphiredev/plugins/blob/main/packages/subcommands/src/lib/Subcommand.ts#L216-L217 so preconditions have already ran by this point
rhh4x0R
rhh4x0R12mo ago
Yeah makes sense. I can run a check manually in my sub commands no problem - I just want to account for the error correctly and return a response, as without that it has all sorts of defer issues.
Favna
Favna12mo ago
yeah so for that implement the subcommand error listeners and if you want to avoid code duplication just extract it to a function and import it in multiple places the events are: https://www.sapphirejs.dev/docs/Documentation/api-plugins/modules/sapphire_plugin_subcommands#subcommandpluginevents
rhh4x0R
rhh4x0R12mo ago
Ah ok so if I implement the sub command error listener, then I can just call one of those sub command errors manually from that new function? For instance the chatinputsubcommanderror, and that’ll hook to the listener? Instead of using throw new UserError for instance.
Favna
Favna12mo ago
not sure if I understand the question correctly but if you implement lets say ChatInputSubcommandError and then in your subcommand you do
if (!myCondition()) {
throw new UserError(...)
}
if (!myCondition()) {
throw new UserError(...)
}
then that error will end up in your impl
rhh4x0R
rhh4x0R12mo ago
Ohhh — that UserError will end up in the sub command error. Got it. How does it know that it’s from a sub command error though if it’s in a separate function outside of the ai command itself? (Basically just trying to figure out how to implement that exactly) — I pass the interaction into the new function which is a sub command chat input — so that will automatically be detected by UserError? Apologies for the verboseness - im used to Rust docs and this is my first TS project so im learning how to navigate the docs.
Favna
Favna12mo ago
the error should be thrown in the subcommand, not the external function. Though I actually dont know if it works when thrown in the external function. I dont think it will... not sure how JS bubbles that up.
rhh4x0R
rhh4x0R12mo ago
I see, gotcha. So I have to if statement on every subcommand. I’ll play around. It’d be cool to get preconditions built in for the sub commands. Maybe I’ll make a wrapper or something.
Favna
Favna12mo ago
it should be possible but I can't make any time guarantees make a GH issue fore it on the plugins repo please
rhh4x0R
rhh4x0R12mo ago
I'll paste my code here for anyone looking for it once I get it. Right now, the UserError doesn't pick up the message. Any ideas?
throw new UserError({ identifier: "permissions", message: 'You must have the role Sensei to use this command.'}) })
throw new UserError({ identifier: "permissions", message: 'You must have the role Sensei to use this command.'}) })
Then on the listener, it picks up the identifier but not messeage. Nevermind, must've been a build error. @favna Do you know how to pull out the identifier in the errorr handling actually?
rhh4x0R
rhh4x0R12mo ago
I can't do error.identifier but it shows up when I console log error
rhh4x0R
rhh4x0R12mo ago
Doh, I have to use UserError instead of Error. It catches the UserError though, too.
MRDGH2821
MRDGH282112mo ago
You will have to provide the type