fix: don't retry melt quote creation on MintOperationError#1090
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
| }, | ||
| retry: (failureCount, error) => { | ||
| if (error instanceof DomainError) { | ||
| if (error instanceof DomainError || error instanceof MintOperationError) { |
There was a problem hiding this comment.
this seems wrong since who knows what else could be the reason to get MintOperationError and maybe for some of those it might make sense to retry. shouldn't we map that exact error case to domain error instead?
There was a problem hiding this comment.
Yea I was wondering that too. We could, but this is only for creating a quote and I couldn't come up with why that should be retryable.
There was a problem hiding this comment.
I guess we can say that but I'd still map limit exceeded to DomainError since it is exactly what we built DomainError for
There was a problem hiding this comment.
@claude lets make the services throw DomainError
There was a problem hiding this comment.
Claude finished @gudnuf's task in 4m 18s —— View job
Mapped MintOperationError → DomainError in services
- Read current implementation in send/receive hooks
- Identify services that call
createMeltQuoteBolt11 - Map
MintOperationErrortoDomainErrorin the services - Revert the non-retryable checks in the hooks
- Run
bun run fix:all(typecheck passes, no new warnings) - Commit changes
What changed
app/features/send/cashu-send-quote-service.ts — getLightningQuote() now wraps the createMeltQuoteBolt11 call. If the mint throws a MintOperationError, it's re-thrown as a DomainError carrying the mint's detail message.
app/features/receive/receive-cashu-token-quote-service.ts — same wrapping around the createMeltQuoteBolt11 call inside createCrossAccountReceiveQuotes / the quote-finding loop.
app/features/send/cashu-send-quote-hooks.ts and app/features/receive/receive-cashu-token-hooks.ts — reverted the useCreateCashuLightningSendQuote and useCreateCrossAccountReceiveQuotes retry checks back to only error instanceof DomainError, and dropped the now-unused MintOperationError import from receive-cashu-token-hooks.ts (kept in send hooks because it's still used by useInitiateCashuSendQuote).
Rationale
Mint operation errors returned from createMeltQuoteBolt11 are definitive responses from the mint (limit exceeded, invoice not allowed, closed-loop 20739, etc.) — there's no scenario where retrying the same request helps. Wrapping them as DomainError at the service boundary is exactly what DomainError is for (user-facing, never retry) and keeps the cashu-ts error type from leaking into the hook retry logic. The mint's detail message is preserved as the DomainError message, so users still see the specific reason.
There was a problem hiding this comment.
An alternative idea to this PR would be to change the scope and focus on addressing all possible mint operation erorrs across flows. For example, we infinitely retry swap that are created with invalid inputs but we should know that error is not retryable.
Not saying this is the exact thing we should do, but orveth proposed classifying the error codes. I can map that out in more detail
There was a problem hiding this comment.
hm not sure about this. are we sure some mint operation errors can't be recoved with retry?
There was a problem hiding this comment.
are we sure some mint operation errors can't be recovered with retry?
I'm sure for these two call sites which are only fetching the melt quote. The PostMeltQuoteBolt11Request looks like
{
"request": <str>,
"unit": <str_enum[UNIT]>,
"options": { // Optional
"amountless": {
"amount_msat": <int>
}
}
}and the only error codes that apply to this request are
- 12001 invalid invoice
- 11005 unit not support
- 11006 amount outside of limit range (min/max melt amount)
- 20006 invoice already paid
- 20739 closed-loop invalid destination
- 3000X auth required
- 3100X rate limitting on minting BATs
So, I would say that specifically for quote creation its safe to not retry. I guess one risk is that some new error code gets added that is retryable, but I can't see what could change between retries (other than rate limit cooldown which isn't a MintOperationError)
There was a problem hiding this comment.
I can change to specifically check for these specific codes above, but it doesn't seem necessary for this case and I think there are very few cases outside of creating a melt quote that would be retryable. In those cases we can be more specific
There was a problem hiding this comment.
An alternative idea to this PR would be to change the scope and focus on addressing all possible mint operation erorrs across flows. For example, we infinitely retry swap that are created with invalid inputs but we should know that error is not retryable.
I think we should do this eventually so might as well do it now. I approved but not sure I would just map it like this and pass the message forward. It might make more sense to use different messages to abstract away some cashu details that don't mean a lot to average user.
Squashed onto post-monorepo master (paths relocated app/ -> apps/web-wallet/app/). Original commits: - fix: don't retry melt quote creation on MintOperationError - refactor: map MintOperationError from melt quote creation to DomainError
e78cd7c to
0c985c8
Compare
Closes #1089
Mint operation errors like
20739(returned when paying a non-allowed invoice with a closed-loop gift card mint) are definitive mint responses and retrying won't help.Updated
useCreateCashuLightningSendQuote(app/features/send/cashu-send-quote-hooks.ts) anduseCreateCrossAccountReceiveQuotes(app/features/receive/receive-cashu-token-hooks.ts) — the two mutations that callcreateMeltQuoteBolt11— to treatMintOperationErroras non-retryable, matching the existing pattern inuseInitiateCashuSendQuoteanduseInitiateMelt.