Custom Arg - ResultError Unwrap failed

This seemed to be working for me in a previous version of Sapphire - but I've only recently gotten back into the swing of things, so there's a good chance I've missed a change. I have a prefix command that has a single arg. The custom arg works great, for returning a result where a result actually does exist (items from item system) Where that item doesn't exist, it throws an error with the identifier "InputNotanItem". When this was working - the first .catch only returned null (which is also a valid response). I've added this catch to try and catch something earlier than my outer try/catch, in case there's some issue there. I can see that the err does include identifier and parameter, but I cannot read these values - I'm assuming it has something to do with this.. ResultError: UnwrapFailed
ResultError: Unwrap failed
at Err.unwrap (F:\Discord Bots\swrpg-bot-v2\node_modules\@sapphire\result\src\lib\Result\Err.ts:108:2)
at Args.rest (F:\Discord Bots\swrpg-bot-v2\node_modules\@sapphire\framework\dist\lib\parsers\Args.js:67:19)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at MarketInfoCommand.messageRun (F:\Discord Bots\swrpg-bot-v2\src\commands\Market\MarketInfoCommand.ts:42:4)
at async F:\Discord Bots\swrpg-bot-v2\node_modules\@sapphire\framework\dist\optional-listeners\message-command-listeners\CoreMessageCommandAccepted.js:20:23
at Object.fromAsync (F:\Discord Bots\swrpg-bot-v2\node_modules\@sapphire\result\src\lib\Result.ts:55:2)
at async CoreListener.run (F:\Discord Bots\swrpg-bot-v2\node_modules\@sapphire\framework\dist\optional-listeners\message-command-listeners\CoreMessageCommandAccepted.js:17:22)
at Object.fromAsync (F:\Discord Bots\swrpg-bot-v2\node_modules\@sapphire\result\src\lib\Result.ts:55:2)
at async CoreListener._run (F:\Discord Bots\swrpg-bot-v2\node_modules\@sapphire\framework\dist\lib\structures\Listener.js:48:22) {
value: ArgumentError: `aaa`was not recognized as an Item.
at Function.error (F:\Discord Bots\swrpg-bot-v2\node_modules\@sapphire\framework\dist\lib\parsers\Args.js:174:30)
at Object.run (F:\Discord Bots\swrpg-bot-v2\src\lib\arguments\DrpgItemArg.ts:18:14)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async Args.restResult (F:\Discord Bots\swrpg-bot-v2\node_modules\@sapphire\framework\dist\lib\parsers\Args.js:55:20)
at async Args.rest (F:\Discord Bots\swrpg-bot-v2\node_modules\@sapphire\framework\dist\lib\parsers\Args.js:66:20)
at MarketInfoCommand.messageRun (F:\Discord Bots\swrpg-bot-v2\src\commands\Market\MarketInfoCommand.ts:42:4)
at async F:\Discord Bots\swrpg-bot-v2\node_modules\@sapphire\framework\dist\optional-listeners\message-command-listeners\CoreMessageCommandAccepted.js:20:23
at Object.fromAsync (F:\Discord Bots\swrpg-bot-v2\node_modules\@sapphire\result\src\lib\Result.ts:55:2)
at async CoreListener.run (F:\Discord Bots\swrpg-bot-v2\node_modules\@sapphire\framework\dist\optional-listeners\message-command-listeners\CoreMessageCommandAccepted.js:17:22)
at Object.fromAsync (F:\Discord Bots\swrpg-bot-v2\node_modules\@sapphire\result\src\lib\Result.ts:55:2) {
identifier: 'InputNotAnItem',
context: null,
argument: { run: [AsyncFunction (anonymous)], name: '' },
parameter: 'aaa'
}
}
ResultError: Unwrap failed
at Err.unwrap (F:\Discord Bots\swrpg-bot-v2\node_modules\@sapphire\result\src\lib\Result\Err.ts:108:2)
at Args.rest (F:\Discord Bots\swrpg-bot-v2\node_modules\@sapphire\framework\dist\lib\parsers\Args.js:67:19)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at MarketInfoCommand.messageRun (F:\Discord Bots\swrpg-bot-v2\src\commands\Market\MarketInfoCommand.ts:42:4)
at async F:\Discord Bots\swrpg-bot-v2\node_modules\@sapphire\framework\dist\optional-listeners\message-command-listeners\CoreMessageCommandAccepted.js:20:23
at Object.fromAsync (F:\Discord Bots\swrpg-bot-v2\node_modules\@sapphire\result\src\lib\Result.ts:55:2)
at async CoreListener.run (F:\Discord Bots\swrpg-bot-v2\node_modules\@sapphire\framework\dist\optional-listeners\message-command-listeners\CoreMessageCommandAccepted.js:17:22)
at Object.fromAsync (F:\Discord Bots\swrpg-bot-v2\node_modules\@sapphire\result\src\lib\Result.ts:55:2)
at async CoreListener._run (F:\Discord Bots\swrpg-bot-v2\node_modules\@sapphire\framework\dist\lib\structures\Listener.js:48:22) {
value: ArgumentError: `aaa`was not recognized as an Item.
at Function.error (F:\Discord Bots\swrpg-bot-v2\node_modules\@sapphire\framework\dist\lib\parsers\Args.js:174:30)
at Object.run (F:\Discord Bots\swrpg-bot-v2\src\lib\arguments\DrpgItemArg.ts:18:14)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async Args.restResult (F:\Discord Bots\swrpg-bot-v2\node_modules\@sapphire\framework\dist\lib\parsers\Args.js:55:20)
at async Args.rest (F:\Discord Bots\swrpg-bot-v2\node_modules\@sapphire\framework\dist\lib\parsers\Args.js:66:20)
at MarketInfoCommand.messageRun (F:\Discord Bots\swrpg-bot-v2\src\commands\Market\MarketInfoCommand.ts:42:4)
at async F:\Discord Bots\swrpg-bot-v2\node_modules\@sapphire\framework\dist\optional-listeners\message-command-listeners\CoreMessageCommandAccepted.js:20:23
at Object.fromAsync (F:\Discord Bots\swrpg-bot-v2\node_modules\@sapphire\result\src\lib\Result.ts:55:2)
at async CoreListener.run (F:\Discord Bots\swrpg-bot-v2\node_modules\@sapphire\framework\dist\optional-listeners\message-command-listeners\CoreMessageCommandAccepted.js:17:22)
at Object.fromAsync (F:\Discord Bots\swrpg-bot-v2\node_modules\@sapphire\result\src\lib\Result.ts:55:2) {
identifier: 'InputNotAnItem',
context: null,
argument: { run: [AsyncFunction (anonymous)], name: '' },
parameter: 'aaa'
}
}
Solution:
After PR 601 (https://github.com/sapphiredev/framework/pull/601) is merged and released then the err.value is no longer needed.
Jump to solution
25 Replies
Bejasc
BejascOP•2y ago
Command (messageRun)
try {
await args
.rest(DrpgItemArg)
.then(async (result) => {
if (result !== "Credits") item = result;

return result;
})
.catch((err) => {
//return null;
console.log(err); //Produces the log above
if (err.identifier === "InputNotAnItem") {
console.error("NOT AN ITEM"); //Not hit, despite the `err` object having `identifier`, as shown in previous console log
}
});

embed = await marketInfoCommandResponse(item, request);
} catch (err) {
//! Not hit at all
//TODO Fix error not working
console.log(err);
if (err instanceof ArgumentError && err.identifier === "InputNotAnItem") embed = Swrpg.warnItemNotFound(err.parameter, request);
else embed = Logger.error(err, "Something went wrong", request.message);
}
try {
await args
.rest(DrpgItemArg)
.then(async (result) => {
if (result !== "Credits") item = result;

return result;
})
.catch((err) => {
//return null;
console.log(err); //Produces the log above
if (err.identifier === "InputNotAnItem") {
console.error("NOT AN ITEM"); //Not hit, despite the `err` object having `identifier`, as shown in previous console log
}
});

embed = await marketInfoCommandResponse(item, request);
} catch (err) {
//! Not hit at all
//TODO Fix error not working
console.log(err);
if (err instanceof ArgumentError && err.identifier === "InputNotAnItem") embed = Swrpg.warnItemNotFound(err.parameter, request);
else embed = Logger.error(err, "Something went wrong", request.message);
}
DrpgItemArg
export default Args.make<IItem | "Credits">(async (parameter, { argument }) => {
const creditsAliaes = ["creds", "credits", "cr"];
if (creditsAliaes.includes(invariant(parameter))) return Args.ok("Credits");

const item = await ItemService.getItem(parameter);

if (item) {
Logger.trace(`DrpgItemArg MATCH: ${item.name} from ${argument}`);
return Args.ok(item);
}

return Args.error({
argument,
parameter,
identifier: "InputNotAnItem",
message: `\`${parameter}\`was not recognized as an Item.`,
});
});
export default Args.make<IItem | "Credits">(async (parameter, { argument }) => {
const creditsAliaes = ["creds", "credits", "cr"];
if (creditsAliaes.includes(invariant(parameter))) return Args.ok("Credits");

const item = await ItemService.getItem(parameter);

if (item) {
Logger.trace(`DrpgItemArg MATCH: ${item.name} from ${argument}`);
return Args.ok(item);
}

return Args.error({
argument,
parameter,
identifier: "InputNotAnItem",
message: `\`${parameter}\`was not recognized as an Item.`,
});
});
I've come across this issue and PR, but I'm not understanding the solution/new approach in sapphiredev/utilities#475 https://github.com/sapphiredev/framework/issues/528 https://github.com/sapphiredev/utilities/pull/475
Bejasc
BejascOP•2y ago
Favna
Favna•2y ago
I can help like near the end of the afternoon (9ish hours) so if anyone from @Helpers can help that'd be great. A few general notes: 1. It would help if you provide a minimal reproduction repository 2. Make sure to dedupe your dependencies. We've had some people having troubles with multiple versions of result.
kyra
kyra•2y ago
That's because err is an unwrapped error, not ArgumentError
Bejasc
BejascOP•2y ago
could you please elaborate? what/how did this change, I'm not sure how to handle the error properly now okay thanks - I'll see what I can do. If I haven't got anywhere in the next hour or two with it - this might take me a few days to pull together - holiday festivities and all
Favna
Favna•2y ago
console log the error to find out what instance it actually is. im not sure from the top of my head either. (it should be ArgumentError still but it might not be unwrapped, contrary to what Kyra said. And if it's not an ArgumentError but another class then it might be a bug in the sapphire code (wouldnt be the first time Kyra wrote something with Result / arg parsing that is actually broken and because Skyra never updated to Framework v3 she tends to be completely oblivious to the bugs it had/has))
Bejasc
BejascOP•2y ago
that's exactly what the message in the OP is - the result of console.log(err) Which... I don't understand, because it doesn't quite look like an object the last ~4 lines do look like an object... and it does mention the value too, about mid-way through the log value - is using the message as provided in my return Args.error({...
Favna
Favna•2y ago
ugh well I can't help much more rn. Im about to leave also.
Bejasc
BejascOP•2y ago
no worries - appreciate you taking a look - happy holidays 🙂
Sawako
Sawako•2y ago
Why is there asynchronous code mixed with synchronous code and is there that asynchronous code inside a trycatch that will never work because the asynchronous code has a .catch? Or were you just testing?
Bejasc
BejascOP•2y ago
Ah, the async inside of the then was left over from testing/trying to fix. Same behaviour with or without it The matching of the arg itself is async It otherwise works as expected, catching, throwing, other than reading the properties off the err
Favna
Favna•2y ago
If you can make a small repro repo after the holidays that'd be great so we can have a proper look at the issue
Bejasc
BejascOP•2y ago
Do you want me to open an Issue on GitHub for it, or just provide the link here?
Bejasc
BejascOP•2y ago
@Helpers as requested - repro repo can be found here https://github.com/Bejasc/repro-sapphire-unwrap-error
GitHub
GitHub - Bejasc/repro-sapphire-unwrap-error
Contribute to Bejasc/repro-sapphire-unwrap-error development by creating an account on GitHub.
24
24•2y ago
Nice
Bejasc
BejascOP•2y ago
Hey @Favna - have you had a chance to check out the repro?
Favna
Favna•2y ago
I havent
Bejasc
BejascOP•2y ago
@Helpers hey folks - wondering if anyone has had a chance to check out the repro above and has any thoughts/ideas they could offer me?
Favna
Favna•2y ago
im looking now @Bejasc
const thing: IThing | null = await args
.pick(ThingArg)
.then((result) => {
return result;
})
.catch((err: ResultError<ArgumentError<IThing>>) => {
console.log(err); //!Generates the output (similar) mentioned in original post https://discord.com/channels/737141877803057244/1056065110038290564/1056065110038290564

if (err.value instanceof ArgumentError && err.value.identifier === "InputNotMatchingThing") {
throw err.value;
} else {
return null;
}
});
const thing: IThing | null = await args
.pick(ThingArg)
.then((result) => {
return result;
})
.catch((err: ResultError<ArgumentError<IThing>>) => {
console.log(err); //!Generates the output (similar) mentioned in original post https://discord.com/channels/737141877803057244/1056065110038290564/1056065110038290564

if (err.value instanceof ArgumentError && err.value.identifier === "InputNotMatchingThing") {
throw err.value;
} else {
return null;
}
});
This fixes the code. Specifically, err.value instead of err. Also typed here to show what the actual type was.
Favna
Favna•2y ago
Favna
Favna•2y ago
Here are all the changes I made. It might just be because you were making the repro but you should mind some of the other changes applied as well such as line 40 in Test.ts Also the way excludes for tsconfig works is that it excludes that what was previously included with includes. So excluding node_modules is only relevant if there is src/node_modules. https://github.com/favna/repro-sapphire-unwrap-error/commit/f197a3b490106e38fbf839f808bd56ffc9040718 (you probably want to click "no whitespace" at the top before looking because I also ran Prettier)
Bejasc
BejascOP•2y ago
Haven't got around to trying this out yet sorry - will let you know when I have
Solution
Favna
Favna•2y ago
After PR 601 (https://github.com/sapphiredev/framework/pull/601) is merged and released then the err.value is no longer needed.
Bejasc
BejascOP•2y ago
Thanks so much for remembering this and getting back to me. Ace support 💯
Favna
Favna•2y ago
You can thank @Vladdy for reminding me of issue 528
Want results from more Discord servers?
Add your server