API Reference
Errors

Error Handling

The Veridex SDK ships a unified error system that normalizes chain-specific errors from EVM, Solana, Starknet, and Stacks into a single VeridexError class. Catch one type everywhere — no more guessing which chain threw what.

VeridexError Class

import { VeridexError, VeridexErrorCode } from '@veridex/sdk';
 
try {
  await sdk.transferViaRelayer({
    targetChain: 10004,
    token: USDC,
    recipient: '0x...',
    amount: 1_000_000n,
  });
} catch (err) {
  if (err instanceof VeridexError) {
    console.log(err.code);      // VeridexErrorCode.INSUFFICIENT_FUNDS
    console.log(err.message);   // "Insufficient funds in vault."
    console.log(err.chain);     // "base"
    console.log(err.retryable); // false
    console.log(err.cause);     // original ethers / RPC error
  }
}

Properties

PropertyTypeDescription
codeVeridexErrorCodeUnified error code (see table below)
messagestringHuman-readable description
chainstring | undefinedChain that produced the error ('base', 'solana', 'starknet', etc.)
causeunknownOriginal chain-specific error object
retryablebooleanWhether the operation could succeed if retried

Error Codes

Wallet & Identity

CodeDefault MessageRetryable
NO_CREDENTIALNo credential set. Call passkey.register() or passkey.setCredential() first.No
UNAUTHORIZEDUnauthorized: the signer is not an owner of this vault.No
INVALID_SIGNATURESignature verification failed.No

Vault State

CodeDefault MessageRetryable
VAULT_NOT_FOUNDVault does not exist. Call ensureVault() first.No
VAULT_PAUSEDVault is paused. Unpause before continuing.No
PROTOCOL_PAUSEDProtocol is paused. Try again later.No

Balance & Limits

CodeDefault MessageRetryable
INSUFFICIENT_FUNDSInsufficient funds in vault.No
DAILY_LIMIT_EXCEEDEDDaily spending limit exceeded. Try a smaller amount or wait for reset.No

Payload & Dispatch

CodeDefault MessageRetryable
INVALID_PAYLOADInvalid action payload.No
INVALID_ACTIONUnknown or invalid action type.No
EXPIREDPrepared transaction has expired. Please prepare again.No

Cross-Chain (Wormhole)

CodeDefault MessageRetryable
VAA_ALREADY_PROCESSEDThis cross-chain message has already been processed (replay protection).No
INVALID_VAAInvalid VAA: verification failed.No
INVALID_EMITTERInvalid emitter: message source is not trusted.No
BRIDGE_ERRORCross-chain bridge error.No

Network & Infrastructure

CodeDefault MessageRetryable
RPC_ERRORRPC call failed. The node may be unavailable.Yes
TIMEOUTOperation timed out.Yes
RELAYER_ERRORRelayer submission failed.Yes

Sessions

CodeDefault MessageRetryable
SESSION_EXPIREDSession key has expired. Create a new session.No
SESSION_INVALIDSession key is invalid or revoked.No

Capability

CodeDefault MessageRetryable
UNSUPPORTED_FEATUREThis feature is not supported on the current chain.No

Catch-All

CodeDefault MessageRetryable
UNKNOWNAn unknown error occurred.No

normalizeError()

The normalizeError function converts any chain-specific error into a VeridexError. The SDK calls this internally at every boundary, but you can use it directly when working with chain clients.

import { normalizeError } from '@veridex/sdk';
 
try {
  await evmClient.dispatch(signature, pubX, pubY, payload, signer);
} catch (err) {
  const veridexErr = normalizeError(err, 'base');
  // veridexErr.code === 'INSUFFICIENT_FUNDS' (if ethers threw "insufficient funds")
}

Chain-Specific Mappings

The normalizer recognizes errors from each chain's native error surface:

EVM regex patterns match against the error message:

PatternMaps To
insufficient fundsINSUFFICIENT_FUNDS
execution reverted.*pausedVAULT_PAUSED
execution reverted.*unauthorized or not ownerUNAUTHORIZED
daily.*limitDAILY_LIMIT_EXCEEDED
nonce.*expired or nonce.*too lowEXPIRED
already.*processed or already knownVAA_ALREADY_PROCESSED
invalid.*signature or ECDSAINVALID_SIGNATURE
timeout or ETIMEDOUT or ECONNREFUSEDTIMEOUT
could not detect network or failed to fetchRPC_ERROR

ethers error codes are also detected:

ethers CodeMaps To
INSUFFICIENT_FUNDSINSUFFICIENT_FUNDS
CALL_EXCEPTIONRPC_ERROR
NETWORK_ERROR / SERVER_ERRORRPC_ERROR (retryable)
TIMEOUTTIMEOUT (retryable)

Handling Patterns

Switch on Error Code

import { VeridexError, VeridexErrorCode } from '@veridex/sdk';
 
try {
  await sdk.transferViaRelayer(params);
} catch (err) {
  if (!(err instanceof VeridexError)) throw err;
 
  switch (err.code) {
    case VeridexErrorCode.INSUFFICIENT_FUNDS:
      showToast('Not enough tokens in your vault');
      break;
 
    case VeridexErrorCode.DAILY_LIMIT_EXCEEDED:
      showToast('Daily limit reached — try again after reset');
      break;
 
    case VeridexErrorCode.SESSION_EXPIRED:
      await sdk.sessions.create({ duration: 3600 });
      break; // retry
 
    case VeridexErrorCode.NO_CREDENTIAL:
      router.push('/login');
      break;
 
    default:
      if (err.retryable) {
        await sleep(2000);
        // retry the operation
      } else {
        showToast(err.message);
      }
  }
}

Retry Retryable Errors

async function withRetry<T>(fn: () => Promise<T>, maxRetries = 3): Promise<T> {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await fn();
    } catch (err) {
      if (err instanceof VeridexError && err.retryable && attempt < maxRetries - 1) {
        await new Promise(r => setTimeout(r, 1000 * 2 ** attempt));
        continue;
      }
      throw err;
    }
  }
  throw new Error('unreachable');
}
 
const result = await withRetry(() => sdk.transferViaRelayer(params));

React Error Boundary

import { VeridexError, VeridexErrorCode } from '@veridex/sdk';
import { Component, type ReactNode } from 'react';
 
class VeridexErrorBoundary extends Component<
  { children: ReactNode; fallback: ReactNode },
  { hasError: boolean; error?: VeridexError }
> {
  state = { hasError: false, error: undefined as VeridexError | undefined };
 
  static getDerivedStateFromError(error: Error) {
    if (error instanceof VeridexError) {
      return { hasError: true, error };
    }
    return { hasError: true };
  }
 
  render() {
    if (this.state.hasError) {
      if (this.state.error?.code === VeridexErrorCode.NO_CREDENTIAL) {
        return <div>Please log in with your passkey.</div>;
      }
      return this.props.fallback;
    }
    return this.props.children;
  }
}

Agent SDK Errors

The Agent SDK (@veridex/agentic-payments) has its own error class:

import { AgentPaymentError, AgentPaymentErrorCode } from '@veridex/agentic-payments';
CodeDescriptionRetryable
LIMIT_EXCEEDEDTransaction exceeds daily or per-tx spending limitNo
INSUFFICIENT_BALANCENot enough tokens in session walletNo
SESSION_EXPIREDSession key has expiredNo
CHAIN_NOT_SUPPORTEDChain ID not in allowedChainsNo
TOKEN_NOT_SUPPORTEDToken not available on target chainNo
NETWORK_ERRORNetwork or RPC failureYes