Appearance
Errors
How Coinbase failures surface and what to do at each step.
How errors surface
- Thrown errors —
connect(),startWithdrawal(),confirmWithdrawal(),getBalances(), etc. reject withConnectSdkError(stablecode). - Events — e.g.
coinbase:sessionExpiredwhen the OAuth token dies mid-flow;oauth:errorfor popup failures.
Branch on code, not on message text:
ts
import {
ConnectSdkError,
ConnectSdkErrorCode,
} from '@swapped/connect-sdk';
try {
await client.coinbase.startWithdrawal({
/* amount, currency, name, … */
});
} catch (error) {
if (!(error instanceof ConnectSdkError)) {
throw error;
}
switch (error.code) {
case ConnectSdkErrorCode.COINBASE_COOLDOWN_ACTIVE: {
const { remainingMs } = client.coinbase.getCooldown();
// Disable start; show countdown
break;
}
case ConnectSdkErrorCode.COINBASE_SESSION_EXPIRED:
case ConnectSdkErrorCode.COINBASE_NOT_CONNECTED:
await client.coinbase.connect();
break;
case ConnectSdkErrorCode.COINBASE_PASSKEY_NOT_SUPPORTED:
// SMS / authenticator, not passkey
break;
case ConnectSdkErrorCode.COINBASE_INVALID_WITHDRAWAL_AMOUNT:
// Field error on amount form
break;
case ConnectSdkErrorCode.SESSION_NOT_ACTIVE:
await client.restartSession();
break;
default:
// API_ERROR / unknown — generic retry
break;
}
}
client.on('coinbase:sessionExpired', () => {
// Token died on the form — back to Connect
});
client.on('oauth:error', ({ error }) => {
// Popup blocked / closed
});When things fail in the flow
| Step | What goes wrong | How you see it | What to do in UI |
|---|---|---|---|
| Connect | Popup blocked or closed early | OAUTH_POPUP_*; also oauth:error | Allow popups; retry connect() |
| Connect / later | OAuth token expired | COINBASE_SESSION_EXPIRED or coinbase:sessionExpired | Call connect() again |
| Any withdraw call | Never connected | COINBASE_NOT_CONNECTED | Call connect() first |
| Amount form | Amount below min / invalid / non-viable above-spendable | Prefer validateWithdrawalAmount for field UX; startWithdrawal auto-adjusts viable above-spendable | Field error or withdrawal callback |
| Start withdraw | Double-submit / retry too soon | COINBASE_COOLDOWN_ACTIVE | Cooldown UI |
| Start / confirm | Passkey-only confirm | COINBASE_PASSKEY_NOT_SUPPORTED | SMS / authenticator |
| Confirm 2FA | Wrong code | Often { status: 'requires2fa' } again | Keep 2FA UI; show feedback; no cooldown |
| Confirm 2FA | Nothing pending | COINBASE_NO_ACTIVE_WITHDRAWAL | Start again |
| Start withdraw | Session already completed | SESSION_NOT_ACTIVE | restartSession() |
Wrong 2FA is usually not a hard error (returns requires2fa again). Cooldown never blocks confirm. In React, use is2faInvalid from useCoinbaseWithdrawal.
Prevent cooldown and amount errors in the UI:
ts
const { isInCooldown, remainingMs } = client.coinbase.getCooldown();
if (isInCooldown) {
// disable Start
}
const validation = await client.coinbase.validateWithdrawalAmount({
amount,
balance,
exchangeRate,
symbol,
network,
});
if (!validation.ok) {
// show validation.reason — do not call startWithdrawal
}Error code reference
| Code | When it happens | What to do |
|---|---|---|
OAUTH_POPUP_BLOCKED | Browser blocked login popup | Allow popups; connect() again |
OAUTH_POPUP_CLOSED | Popup closed early | Retry connect() |
COINBASE_NOT_CONNECTED | No OAuth token | Call connect() |
COINBASE_SESSION_EXPIRED | Token invalid | Reconnect; listen for coinbase:sessionExpired |
COINBASE_INVALID_WITHDRAWAL_AMOUNT | Below min, invalid, or above spendable with no viable cap | Validate first; see withdrawal auto-adjust |
COINBASE_COOLDOWN_ACTIVE | Start during 30s cooldown | Wait; use getCooldown() |
COINBASE_PASSKEY_NOT_SUPPORTED | Passkey confirmation required | SMS / authenticator 2FA |
COINBASE_NO_ACTIVE_WITHDRAWAL | Confirm with nothing pending | startWithdrawal first |
SESSION_NOT_ACTIVE | Session cannot accept a new payment | restartSession() |
Unmapped HTTP failures surface as API_ERROR. Show a retry message and keep the user on the same step when safe.