Common failure scenarios
User Rejection
The user saw the approval screen and chose not to approve. This is expected, normal user behavior — not an error. Reset your UI gracefully without showing an error message.
Policy Violation
The user approved, but the smart wallet’s policy blocked execution — for example, a spending limit was exceeded or the contract isn’t on the wallet’s allowlist.
Contract Execution Error
The transaction was authorized and submitted, but the Soroban contract panicked or returned an error during execution. No state changes were applied.
Network / Submission Error
The transaction failed to reach or be processed by the network due to connectivity issues, RPC timeouts, or ledger congestion. These are often transient — a retry may succeed.
Fee Failure
The wallet’s fee evaluation returned
CannotProceed — the fee asset isn’t supported, the calculated fee exceeds max_total_fee, or the deferred fee balance has reached its cap.Authentication / Session Error
The user’s session token has expired or is invalid. The user needs to re-authenticate before attempting any transaction.
Error codes
SocketFi throws structured errors with acode property that lets you handle specific failure scenarios programmatically:
Complete error handling example
The following example demonstrates handling multiple error types from a singlerequestTransaction() call:
UI patterns for failures
Good failure UX shares three properties: it explains what happened in plain language, it offers a clear path forward, and it preserves the user’s context so they don’t have to start over. Explain, don’t expose. Translate error codes into user-facing language. “Your wallet rejected this transaction due to a policy limit” is more useful than “TRANSACTION_REJECTED.” Reserve raw error codes for developer logs. Distinguish rejection from failure. A user who cancels the approval screen made an intentional choice. Don’t show them a red error banner — just reset the form to its ready state. Reserve error messaging for genuine failures. Offer retry when appropriate. Network errors and transient fee issues are often retryable. Contract errors and policy violations usually aren’t — the underlying condition needs to change before a retry will succeed. Only show a retry button when there’s a reasonable expectation it will help. Preserve form state. If a transfer fails because the popup was blocked, the user shouldn’t have to re-enter the recipient address and amount. Keep form values intact when transitioning to an error state.Handling failures at each lifecycle stage
Different failure types occur at different points in the transaction lifecycle. Understanding where a failure originates helps you craft the right response:When
result.success is false, you can’t always determine the exact cause from the TransactionResult alone — use try/catch to capture thrown errors with specific code values, which provide more precise failure information for your error handling logic.