Skip to content

Errors

How Coinbase failures surface in React and what to do at each step.

How errors surface

  1. Hook error stateuseCoinbaseConnection().error, useCoinbaseWithdrawal().error, balances/networks hooks, etc.
  2. Thrown / rejected promises — the same actions also reject (hooks rethrow after setting error).
  3. Events — e.g. useOnCoinbaseSessionExpired; useOnOAuthError / useOnError for popup failures.

Amount validation errors

useCoinbaseAmount().error / .warning are CoinbaseAmountError ({ crypto, fiat }), not strings. Each half is an AmountValidationError ({ code, message, metadata }); fiat is null when no exchange rate. Switch on error.crypto.code for i18n; use error.crypto.message / error.fiat?.message as English fallbacks.

Codes: invalid_amount, amount_zero, below_min, above_balance (hard: above raw balance), above_spendable (soft: above balance minus fee reserve). In 'balance' mode (default), above_spendable is a non-blocking warning; in 'spendable' mode it is a blocking error.

Typed SDK failures are ConnectSdkError with a stable code. Branch on that instead of parsing message:

tsx
import { ConnectSdkError, ConnectSdkErrorCode } from '@swapped/connect-sdk'
import {
  useCoinbaseConnection,
  useCoinbaseWithdrawal,
  useCoinbaseWithdrawalCooldown,
  useOnCoinbaseSessionExpired,
} from '@swapped/connect-sdk/react'

function WithdrawWithErrors() {
  const { connect, error: connectError } = useCoinbaseConnection()
  const { startWithdrawal, error: withdrawError } = useCoinbaseWithdrawal()
  const { isInCooldown, remainingMs } = useCoinbaseWithdrawalCooldown()

  useOnCoinbaseSessionExpired(() => {
    // Token died on the form — back to Connect
  })

  async function onStart() {
    if (isInCooldown) return

    try {
      // Builds the request from CoinbaseProvider selection
      await startWithdrawal()
    } catch (error) {
      if (
        error instanceof ConnectSdkError &&
        error.code === ConnectSdkErrorCode.COINBASE_PASSKEY_NOT_SUPPORTED
      ) {
        // SMS / authenticator, not passkey
      }
    }
  }

  const error = connectError ?? withdrawError
  let message: string | null = null
  if (error instanceof ConnectSdkError) {
    switch (error.code) {
      case ConnectSdkErrorCode.OAUTH_POPUP_BLOCKED:
        message = 'Allow popups for this site, then try connecting again.'
        break
      case ConnectSdkErrorCode.COINBASE_SESSION_EXPIRED:
        message = 'Your Coinbase session expired. Please connect again.'
        break
      case ConnectSdkErrorCode.COINBASE_PASSKEY_NOT_SUPPORTED:
        message =
          'Passkey confirmation is not supported. Use SMS or an authenticator app.'
        break
      case ConnectSdkErrorCode.COINBASE_COOLDOWN_ACTIVE:
        message = `Please wait ${Math.ceil(remainingMs / 1000)}s before trying again.`
        break
      default:
        message = error.message
    }
  } else if (error) {
    message = error.message
  }

  return (
    <div>
      {message && <p>{message}</p>}
      <button type="button" disabled={isInCooldown} onClick={() => void onStart()}>
        Withdraw
      </button>
      <button type="button" onClick={() => void connect()}>
        Reconnect
      </button>
    </div>
  )
}

When things fail in the flow

StepWhat goes wrongHow you see itWhat to do in UI
ConnectPopup blocked or closedOAUTH_POPUP_* on connection error; useOnOAuthErrorAllow popups; retry
Connect / laterToken expiredCOINBASE_SESSION_EXPIRED or useOnCoinbaseSessionExpiredconnect() again
Any withdraw callNever connectedCOINBASE_NOT_CONNECTEDConnect first
Amount formAmount below min / invalid / above balance / non-viable above-spendablePrefer useCoinbaseAmount; startWithdrawal auto-adjusts viable above-spendableField error / warning or withdrawal callback
Start withdrawMissing token / amountCOINBASE_SELECTION_INCOMPLETEComplete selection under CoinbaseProvider
Start withdrawDouble-submitCOINBASE_COOLDOWN_ACTIVEuseCoinbaseWithdrawalCooldown
Start / confirmPasskey-onlyCOINBASE_PASSKEY_NOT_SUPPORTEDSMS / authenticator
Confirm 2FAWrong coderequires2fa again; hook sets is2faInvalidKeep 2FA UI; show feedback; clear2faInvalid on edit
Confirm 2FANothing pendingCOINBASE_NO_ACTIVE_WITHDRAWALStart again
Start withdrawSession completedSESSION_NOT_ACTIVErestartSession()

Wrong 2FA keeps status: 'requires2fa'. The React hook sets is2faInvalid for UI feedback (not error / hard failure). Cooldown never blocks confirm.

Error code reference

CodeWhen it happensWhat to do
OAUTH_POPUP_BLOCKEDBrowser blocked login popupAllow popups; connect() again
OAUTH_POPUP_CLOSEDPopup closed earlyRetry connect()
COINBASE_NOT_CONNECTEDNo OAuth tokenCall connect()
COINBASE_SESSION_EXPIREDToken invalidReconnect; useOnCoinbaseSessionExpired
REACT_COINBASE_PROVIDER_REQUIREDHook used outside CoinbaseProviderWrap with CoinbaseProvider
COINBASE_SELECTION_INCOMPLETEstartWithdrawal() without token/amountComplete selection first
COINBASE_INVALID_WITHDRAWAL_AMOUNTBelow min, invalid, or above spendable with no viable capFix amount; see withdrawal auto-adjust
COINBASE_COOLDOWN_ACTIVEStart during 30s cooldownuseCoinbaseWithdrawalCooldown
COINBASE_PASSKEY_NOT_SUPPORTEDPasskey confirmation requiredSMS / authenticator 2FA
COINBASE_NO_ACTIVE_WITHDRAWALConfirm with nothing pendingstartWithdrawal first
SESSION_NOT_ACTIVESession cannot accept a new paymentrestartSession()

Unmapped HTTP failures surface as API_ERROR. Show a retry message and keep the user on the same step when safe.