failure instead of throwing. This page covers both.
Every error the SDK throws extends BaseError and has a code. Check the class with instanceof, and use error.code to tell cases of the same class apart. Do not match on error.message, because its text can change. Import every class from @dynamic-labs-sdk/client.
Error classes
The sections below describe when each one happens and what your UI should do.
FlowNotFoundError
The flow does not exist, or it belongs to a different environment than the Dynamic client’s. Retrying does not help. Check the flow ID and the client’senvironmentId, and show a “payment not found” screen. The functions that need a session token report an unknown flow as FlowSessionExpiredError instead.
FlowSourceBlockedError
Screening blocked the payment source.reason says which check blocked it:
sanctions_blocked: the wallet failed screening when it was attached, or when adepositmode quote changed the amount. When attaching, nothing is saved, so the payer can attach another wallet or choose another source.risk_blocked: a quote found the flow blocked by risk screening. The payer can attach a different source on the same flow.
FlowExchangeSourceError
The exchange cannot be attached as the payment source.retryable is true only for exchange_unavailable.
List only the exchanges that
getFlowSupportedExchanges returns to avoid most of these errors.
FlowQuoteAmountError
The quote rejected the amount the payer chose. This applies only todeposit mode, where the payer can change the amount.
amount_invalid: the amount is malformed, too precise, or too small. Use at most 2 decimals forUSDand at most the token’s decimals forSOURCE_TOKEN. Ask the payer for a valid amount.amount_not_editable: the flow’s amount is fixed, because the flow is not indepositmode. Stop sendingamountfor this flow.
FlowQuoteUnavailableError
No route was found to any token the flow settles in, so the quote failed.quoteFailures explains why each settlement token could not be quoted, and Quote failures lists the reasons.
FlowPrepareSigningError
Preparing the wallet transaction failed before anything was signed or sent.quote_expired: the quote expired, which happens 60 seconds after a wallet quote. Get a new quote withgetFlowQuote, then let the payer confirm again.insufficient_balance: the wallet cannot cover the transfer amount or the gas. Ask the payer to fund the wallet or pay with another token.
FlowStateConflictError
The action conflicts with the flow’s current state.code carries the reason, and retryable is true only for flow_concurrent_update.
New codes can be added, so treat an unknown code like
flow_invalid_transition. The React mutation hooks refetch the flow on this error, so useGetFlow shows the real state.
FlowSessionTokenMissingError and FlowSessionExpiredError
Every action after attaching a source needs the flow’s session token, which the SDK stores on the device when the source is attached. The two errors differ in whether a token was stored:FlowSessionTokenMissingError: no token for the flow is stored on this device. The source was attached on another device, the payer cleared storage, or no source was attached yet.FlowSessionExpiredError: a token was stored, but the server no longer accepts it. The token was revoked, expired, or replaced when a source was attached again on another device, or the flow ended. The SDK removes the stored token before it throws.
getFlow. If the flow exists and the payment has not been sent, attach the source again, which stores a new token on this device. Otherwise, show the flow’s state. Reload and another device shows the code.
UserRejectedError
The payer declined a wallet prompt duringsubmitFlowTransaction. Nothing was sent, and the SDK requested a new quote with the same token and chain before it threw, so the flow is ready for another attempt. Tell the payer the payment was not approved, and let them submit again or choose another way to pay. Do not cancel the flow.
InvalidParamError
The wallet’s chain cannot sign Flow payments.submitFlowTransaction supports wallets on EVM, Solana, Bitcoin, Sui, and TRON. Ask the payer to use a wallet on one of those chains.
Quote failures
FlowQuoteUnavailableError.quoteFailures has one entry for each settlement token that could not be quoted, with the token’s chainId, chainName, and symbol, and a reason:
Errors without a class
Some rejections have no dedicated class. Showerror.message for them, and let the payer change their choice:
- The flow sets
disableSwaps, and the payer’s token and chain do not match a settlement. Ask the payer to pay with a token and chain you settle in. - The payer’s token cannot be priced.
- A deposit address is not available for the chosen chain and token.
- The SDK could not get the transaction to sign during
submitFlowTransaction. Nothing was sent; read the flow and let the payer confirm again fromquoted.
When to retry
Most errors leave the flow unchanged, but after the payer approves a wallet payment, an error does not prove that nothing was sent. Follow these rules forsubmitFlowTransaction:
- After
UserRejectedError, the payer can submit again. The SDK already got a new quote. - After
FlowPrepareSigningErrorwith codequote_expired, get a new quote, then let the payer submit again. - After any other error, do not retry. Call
getFlowand show the screen for its state. A flow still inquotedwas not sent, and the payer can confirm again. A flow insigningor later may have been sent, so show it as processing. A second approval could send a second payment.
FlowStateConflictError with retryable (after reading the flow), FlowExchangeSourceError with retryable, and quote failures whose reason is provider_rate_limited or provider_unavailable.
Failures after the payment is sent
Once the payment is sent, nothing throws. If the payment or its delivery fails, the flow’sexecutionState or settlementState becomes failed, and flow.failure describes why:
Related
- Build a custom payment UI: where each error appears in the payment UI.
- Flow payments API errors: the HTTP errors behind these classes.
- Failures and refunds: failure codes and refunds.