Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.cavos.xyz/llms.txt

Use this file to discover all available pages before exploring further.

Error Classes

JwtExpiredError

Thrown by execute() when the OAuth JWT has expired and the session is not yet registered on-chain. The user must re-authenticate.
import { JwtExpiredError } from '@cavos/react';

try {
  await execute(calls);
} catch (err) {
  if (err instanceof JwtExpiredError) {
    // Prompt re-login
    await login('google');
  }
}
JWTs from Google/Apple typically expire after 1 hour. Once the session key is registered on-chain (first transaction), subsequent transactions use the session key directly — no JWT needed until the session itself expires.

Authentication Errors

OAuth Login Cancelled or Blocked

try {
  await login('google');
} catch (error) {
  if (error.message.includes('closed without completing')) {
    showMessage('Login window was closed. Please try again.');
  } else if (error.message.includes('timed out')) {
    showMessage('Login timed out. Please try again.');
  }
}

Nonce Mismatch

Happens if session state was corrupted between the OAuth redirect and the callback:
try {
  await login('google');
} catch (error) {
  if (error.message.includes('nonce')) {
    // Clear any stale state and retry
    sessionStorage.clear();
    await login('google');
  }
}

Session Errors

Session Not Registered

Thrown when execute() is called with gasless: false before any on-chain session exists:
try {
  await execute(calls, { gasless: false });
} catch (error) {
  if (error.message.includes('non-sponsored transaction without a registered session')) {
    // Execute one sponsored tx first — it registers the session automatically
    await execute(calls); // gasless: true (default)
    // Now retry with user-pays
  }
}

Session Expired (Beyond Grace Period)

try {
  await execute(calls);
} catch (error) {
  if (error.message.includes('SESSION_EXPIRED')) {
    // Session expired beyond the 48h grace window — must re-login
    await login('google');
  }
}

Session Expired (Within Grace Period)

The SDK handles this automatically — execute() will call renewSession() internally before proceeding. You don’t need to handle this case explicitly.

Wallet Not Initialized

try {
  await execute(calls);
} catch (error) {
  if (error.message.includes('not initialized') || error.message.includes('Please login')) {
    await login('google');
  }
}

Transaction Errors

Session Policy Violation

try {
  await execute(calls);
} catch (error) {
  if (error.message.includes('Spending limit exceeded')) {
    showMessage('This transaction exceeds your session spending limit.');
  } else if (error.message.includes('not in allowedContracts') || error.message.includes('policy')) {
    showMessage('This contract is not permitted by your session policy.');
  }
}

Paymaster Error

try {
  await execute(calls);
} catch (error) {
  if (error.message.includes('paymaster') || error.message.includes('gas tank')) {
    showMessage('Gasless sponsorship is temporarily unavailable. Try again shortly.');
  }
}

Insufficient Balance (User-Pays)

try {
  await execute(calls, { gasless: false });
} catch (error) {
  if (error.message.includes('insufficient') || error.message.includes('max_fee')) {
    showMessage('Insufficient STRK balance for transaction fee.');
  }
}

Contract / Entrypoint Not Found

try {
  await execute(calls);
} catch (error) {
  if (error.message.includes('Contract not found')) {
    showMessage('Contract does not exist on this network.');
  } else if (error.message.includes('Entry point not found')) {
    showMessage('Function does not exist on this contract.');
  }
}

Wallet Errors

Account Not Deployed

try {
  await execute(calls);
} catch (error) {
  if (error.message.includes('not deployed')) {
    // Deployment normally happens automatically — trigger manually if needed
    await deployAccount();
    await execute(calls);
  }
}

Address Seed Mismatch

Happens when the identity (sub) or app salt doesn’t match what the wallet was created with:
try {
  await login('google');
} catch (error) {
  if (error.message.includes('Address seed mismatch')) {
    // Identity verification failed — clear state and re-authenticate
    await logout();
    await login('google');
  }
}

MAU Limit Exceeded

try {
  await login('google');
} catch (error) {
  if (error.message.includes('MAU limit')) {
    showMessage('App has reached its monthly active user limit.');
  }
}

Network Errors

RPC Timeout or Rate Limit

try {
  await execute(calls);
} catch (error) {
  if (error.message.includes('timeout') || error.message.includes('network')) {
    showMessage('Network error. Please check your connection and try again.');
  }
}
To avoid rate limits on the default shared RPC, provide your own:
<CavosProvider config={{
  appId: 'your-app-id',
  starknetRpcUrl: 'https://your-own-rpc-node.com',
}}>

Debugging

Enable Logging

<CavosProvider config={{
  appId: 'your-app-id',
  enableLogging: true,
}}>

Inspect Wallet State

const { isAuthenticated, address, walletStatus, sessionPublicKey } = useCavos();

console.log({
  isAuthenticated,
  address,
  sessionPublicKey,
  walletStatus, // { isDeploying, isDeployed, isRegistering, isSessionActive, isReady, pendingDeployTxHash? }
});

Error Recovery Reference

ErrorCauseRecovery
JwtExpiredErrorOAuth JWT expired before session was registeredRe-login via login()
SESSION_EXPIREDSession expired past 48h grace windowRe-login via login()
non-sponsored transaction without a registered sessiongasless: false before first txExecute a sponsored tx first
Spending limit exceededTransaction exceeds session policy limitCheck spendingLimits in policy
Address seed mismatchIdentity/salt mismatchLogout and re-login
MAU limitApp exceeded monthly usersUpgrade plan or wait for reset
paymaster / gas tankPaymaster temporarily unavailableRetry, or use gasless: false
not initializedexecute() called before login()Call login() first
timeoutRPC timeoutRetry, or configure a custom RPC URL