TrustwareError. Routing failures, rate limits, and a few validation checks use their own classes or a plain Error, covered below. You can handle errors reactively via the onError callback, imperatively by catching thrown errors in the headless core, or by listening for the error event in the lifecycle events stream.
The TrustwareError class
TrustwareError extends the native Error class with three additional fields:
Import it directly from the SDK:
Error codes
TheTrustwareErrorCode enum lists the codes a TrustwareError can carry.
Handling errors via onError
Pass an onError callback in your TrustwareConfigOptions to receive all errors emitted by the widget and provider. This is the simplest approach for most integrations.
error.userMessage when it is defined:
Handling errors with try/catch
When using the headless core API, errors are thrown as exceptions. Wrap core calls in atry/catch block.
Errors that are not TrustwareError
Some SDK rejections are not a TrustwareError, so an instanceof TrustwareError check will not match them. Check the exported classes, such as RouteExpiredError, ReceiptCommitError, and RateLimitError, with instanceof, and a RouteError with isRouteError(). Match by name or by message only for a plain Error that has no exported class.
Destination posthook validation
Trustware.buildRoute() and Trustware.buildDepositAddress() reject a structurally incomplete hooks.postHook before sending the request.
fullAmount and amountInputPos are provider dependent. See amount patching.
These checks confirm the request is complete. They do not verify that your calldata is correct, that target is a contract, or that the destination call will succeed. The API is authoritative for everything the client cannot check, and rejects a posthook it will not route with a 400 and a message describing the problem. See vault destinations.
Source token approvals
Trustware.sendRouteTransaction() can submit ERC-20 approvals before the route transaction. Four failures can surface from that step.
All four are recoverable. Let the user retry rather than treating the deposit as failed.
SDKRPCError is not exported from the package, so identify it by error.name rather than with instanceof.
Route approvals with no usable amount
Trustware.buildRoute() throws a plain Error when a route.execution.approvals entry has an amount that is missing or not a whole number. Requires SDK 1.1.18 or later.
Treat it like any other failed build and let the user try again.
Expired routes
Trustware.sendRouteTransaction(), Trustware.sendReviewedRoute(), and sendRouteAsUserOperation() throw RouteExpiredError when the route’s expiresAt has passed. The route transaction was not sent, but approvals that already confirmed stay on chain. Build a new route. On a Solana route, sendReviewedRoute() checks the route it rebuilds right before signing, not the one you reviewed. Requires SDK 1.1.18 or later.
Trustware.buildRoute() and Trustware.buildDepositAddress() throw RouteResponseError when a route response has no valid expiresAt or Date header. Its field says which. See RouteResponseError.
Refused receipts
Trustware.submitReceipt() throws ReceiptCommitError when Trustware refuses the commit. Branch on error.retryable or error.code, never on the message. retryable is true only for the codes that mean “retry shortly”, so a code your SDK version doesn’t know is final. Requires SDK 1.1.18 or later.
A resolved poll is not a success
Trustware.pollStatus() resolves when the route reaches success, failed, or expired, and when polling times out. A timeout resolves with the last status it saw, which can be pending, submitted, bridging, or a value newer than your SDK version. Always branch on the status.
Polling stops at expired from SDK 1.1.18. Earlier versions keep polling an expired intent until the timeout.
Polling an intent that has no receipt yet
Before a receipt is submitted, status resolves with"pending", a stub with no transaction fields, so check status before reading sourceTxHash, toAmountWei, or any other transaction field. pollStatus keeps polling through it.
A 404 is different. It means the intent ID is unknown, so the SDK throws out of the poll loop rather than retrying to the timeout. Catch it as a terminal failure. The SDK throws it as an Error named "HttpError" with a numeric status. HttpError is not exported, so check name and status rather than the message.
The RouteError class
When the routing API cannot produce a route, Trustware.buildRoute() and Trustware.buildDepositAddress() throw a RouteError. It extends the native Error class directly (not TrustwareError), so an instanceof TrustwareError check will not match it. message is the API’s one-line summary, as in earlier versions. Requires SDK 1.1.15 or later; through 1.1.13 these methods throw a plain Error.
status, code, and the provider codes match the endpoint’s error responses. buildRoute() rejects a malformed address itself with a plain Error, so invalid_address covers what only the API can check, such as a wrong EVM checksum.
Routes whose fees exceed their output
buildRoute() and buildDepositAddress() refuse a route whose fees exceed what it delivers, and sendRouteTransaction() refuses one before the wallet is asked to sign. The RouteError has status 0 and code "fees_exceed_output", with one provider entry carrying the same code. The API runs a similar check and reports a losing route as a fees_exceed_output decline, so branch on the provider code to handle both.
isRouteError() also recognizes a RouteError thrown by another copy of the SDK bundle, so prefer it over instanceof.
parseRouteError(value) returns the same facts, plus the minimum amount a provider asked for when one did, or null when the value carries no routing verdict. formatMinimum(minimum) renders that minimum for display.
The RateLimitError class
When your integration hits the API rate limit, the SDK surfaces the 429 as a RateLimitError. It extends the native Error class directly (not TrustwareError), so a single instanceof TrustwareError check will not match it; handle it as a separate case.
The SDK has already waited out the limit on the server’s own schedule before throwing, so do not retry straight away. retriesExhausted says which case you are in: false means the wait is known and longer than the SDK will block for, so rateLimitInfo.retryAfter tells the user when to come back; true means the response carried no usable timing at all.
retriesExhausted cases, and the monitoring callbacks.
The rateLimitInfo property has the following shape:
