SDK error handling

Catch and react to Bridge SDK failures with TokeflowError and the full TokeflowErrorCode reference — switch on stable codes, surface friendly messages, and centralize logging with a global onError handler.

Every failure in the Bridge SDK is reported as a TokeflowError — a typed error with a stable, machine-readable code. Switch on code to drive your UI, show message to humans, and log requestId for support.

The SDK throws (or rejects promises with) TokeflowError for everything from a misconfigured key to an incomplete card field to a network timeout. Because the codes are stable, you can build your error handling once and rely on it across tokenization, checkout, and wallet flows.

For server-side API errors (the error envelope returned by https://api.tokeflow.com), see Errors. This page covers errors raised in the browser by the Bridge SDK.

The TokeflowError class

TokeflowError extends the native Error, so error.message and instanceof Error work as usual. It adds a code and optional transport context.

class TokeflowError extends Error {
  code: TokeflowErrorCode; // stable machine-readable code — switch on this
  message: string;         // human-readable explanation (display-safe, may reword)
  httpStatus?: number;     // HTTP status, when the error came from an API call
  requestId?: string;      // request id (req_…) for support, when available
  details?: unknown;       // optional structured context about the failure
}
PropertyTypeAlways presentDescription
codeTokeflowErrorCodeYesStable, machine-readable code. Switch on this. See the full table.
messagestringYesHuman-readable explanation. Display-safe, but may change wording over time — never parse it.
httpStatusnumberNoPresent when the error originated from an API request (e.g. 429, 500).
requestIdstringNoRequest identifier (req_…) for the underlying API call, when available. Log it.
detailsunknownNoOptional structured context about the failure.

Treat code as the stable contract and message as display-only. Always log requestId and httpStatus — they make support requests far faster to resolve.

How errors flow

A TokeflowError surfaces in two places: it rejects the promise of the call that failed (so you handle it with try/catch), and — if you configured one — it is also passed to the global onError handler.

Handling errors with try/catch

Wrap SDK calls in try/catch, narrow to TokeflowError with instanceof, then switch on error.code to map each failure to user-facing copy. Always keep a default branch.

import { TokeflowError, TokeflowErrorCode } from '@tokeflow_com/bridge-js';

try {
  const token = await tokeflow.cards.tokenize({ card: cardElement });
  // Send token.tokenId to your backend to create the transaction.
} catch (error) {
  if (error instanceof TokeflowError) {
    switch (error.code) {
      case TokeflowErrorCode.ELEMENT_INCOMPLETE:
        showError('Please complete all card fields.');
        break;
      case TokeflowErrorCode.INVALID_CARD:
        showError('Please check your card number.');
        break;
      case TokeflowErrorCode.INVALID_CPF:
        showError('Please check the CPF you entered.');
        break;
      case TokeflowErrorCode.EXPIRED_CARD:
        showError('This card has expired.');
        break;
      case TokeflowErrorCode.UNSUPPORTED_CARD_BRAND:
        showError('This card brand is not supported.');
        break;
      case TokeflowErrorCode.PAYMENT_METHOD_DISABLED:
        showError('That payment method is not available right now.');
        break;
      case TokeflowErrorCode.SESSION_EXPIRED:
        showError('Your session expired. Please refresh and try again.');
        break;
      case TokeflowErrorCode.RATE_LIMITED:
        showError('Too many attempts. Please wait a moment and try again.');
        break;
      case TokeflowErrorCode.NETWORK_ERROR:
      case TokeflowErrorCode.TIMEOUT:
        showError('Network problem. Please try again.');
        break;
      default:
        showError(error.message);
    }

    // Log the transport context for support and monitoring.
    console.error('Tokeflow error', {
      code: error.code,
      httpStatus: error.httpStatus,
      requestId: error.requestId,
      details: error.details,
    });
  } else {
    // Not a TokeflowError — rethrow or handle as a generic failure.
    throw error;
  }
}

error.code is a value from the TokeflowErrorCode enum. Compare against the enum (e.g. TokeflowErrorCode.INVALID_CARD) rather than the raw string so a typo becomes a compile-time error in TypeScript.

Many input failures are avoidable before a round trip. Read an element's getState() ({ empty, valid, invalid, complete }) and keep your pay button disabled until state.complete && state.valid. This prevents most ELEMENT_INCOMPLETE and ELEMENT_INVALID errors. See Tokenization.

Global onError handler

Pass an onError callback in the SDK config to receive every TokeflowError in one place — ideal for centralized logging and monitoring. It complements try/catch; it does not replace it. Use onError for observability and your local catch for the user-facing reaction at the point of failure.

import { TokeflowBridge } from '@tokeflow_com/bridge-js';

const tokeflow = new TokeflowBridge({
  publicKey: 'pk_live_mer_your_public_key',
  onError: (error) => {
    // Centralized logging — runs for every TokeflowError the SDK raises.
    logToService({
      code: error.code,
      message: error.message,
      httpStatus: error.httpStatus,
      requestId: error.requestId,
    });
  },
});

Keep onError side-effect-only (logging, metrics). Do not throw from inside it, and do not use it to control your checkout flow — drive the UI from the catch block at the call site, where you have local context.

In React, configure onError on the provider config, and read the current error from the useTokeflow() hook:

import { TokeflowProvider, useTokeflow } from '@tokeflow_com/bridge-js/react';

function App() {
  return (
    <TokeflowProvider
      config={{
        publicKey: 'pk_live_mer_your_public_key',
        onError: (error) => logToService({ code: error.code, requestId: error.requestId }),
      }}
    >
      <Checkout />
    </TokeflowProvider>
  );
}

function Checkout() {
  const { isReady, error } = useTokeflow();

  if (error) return <div role="alert">{error.message}</div>;
  if (!isReady) return <div>Loading…</div>;

  // render your payment form
}

TokeflowErrorCode reference

Every error the SDK raises carries one of these codes. They are grouped here by lifecycle stage for readability; the enum itself is flat.

Configuration and initialization

CodeDescription
INVALID_CONFIGThe SDK configuration is invalid (bad or conflicting options).
INVALID_PUBLIC_KEYThe public key is missing or not a valid pk_… key.
NOT_IN_BROWSERThe SDK was used outside a browser environment (e.g. during server-side rendering).
NOT_INITIALIZEDAn SDK method was called before init() resolved.

Session lifecycle

CodeDescription
SESSION_CREATION_FAILEDThe SDK could not create a session during init().
SESSION_EXPIREDThe session has expired and was not refreshed.
SESSION_REFRESH_FAILEDA background or manual session refresh failed.

Elements and input validation

CodeDescription
ELEMENT_NOT_MOUNTEDThe operation requires an element that has not been mounted to the DOM.
ELEMENT_INVALIDAn element's value is invalid.
ELEMENT_INCOMPLETEAn element's input is incomplete (a required field is not fully entered).
VALIDATION_ERRORInput validation failed.
INVALID_CARDThe card number failed validation.
INVALID_CPFThe CPF failed validation.
EXPIRED_CARDThe card's expiry date is in the past.

Tokenization

CodeDescription
TOKENIZATION_FAILEDTokenization could not be completed.
TOKEN_REGISTRATION_FAILEDThe token could not be registered with the backend.

Checkout

CodeDescription
NO_CHECKOUT_SESSIONA checkout call was made without a linked checkoutSessionId.
CHECKOUT_CONTEXT_FETCH_FAILEDThe checkout context could not be fetched.

Payment and wallets

CodeDescription
PAYMENT_METHOD_DISABLEDThe payment method is not enabled for this merchant.
UNSUPPORTED_CARD_BRANDThe card brand is not supported.
PAYMENT_CANCELLEDThe payment was cancelled (e.g. the Apple Pay or Google Pay sheet was dismissed).
PAYMENT_FAILEDThe payment failed.

Transport

CodeDescription
NETWORK_ERRORA network request failed.
TIMEOUTA request timed out.
RATE_LIMITEDToo many requests — the client is being rate limited.
SERVER_ERRORThe server returned an error.

RATE_LIMITED, SERVER_ERROR, NETWORK_ERROR, and TIMEOUT typically carry an httpStatus and a requestId. For transient transport failures, retry with exponential backoff rather than retrying immediately. See Idempotency and rate limits.

Different categories call for different responses. Use this as a starting policy.

CategoryExample codesWhat to do
Fix the integrationINVALID_CONFIG, INVALID_PUBLIC_KEY, NOT_IN_BROWSER, NOT_INITIALIZEDBugs in your setup. Surface during development; do not show raw text to end users.
Ask the user to correct inputELEMENT_INCOMPLETE, ELEMENT_INVALID, INVALID_CARD, INVALID_CPF, EXPIRED_CARD, VALIDATION_ERRORShow a field-level, actionable message and let the user retry.
Recover the sessionSESSION_EXPIRED, SESSION_REFRESH_FAILED, SESSION_CREATION_FAILEDRe-initialize the bridge or prompt the user to refresh, then retry.
Adjust the offerPAYMENT_METHOD_DISABLED, UNSUPPORTED_CARD_BRANDOffer a different payment method or card.
Expected user actionPAYMENT_CANCELLEDTreat as a benign cancellation — return the user to the payment step without an error banner.
Retry with backoffNETWORK_ERROR, TIMEOUT, RATE_LIMITED, SERVER_ERRORRetry transient failures with exponential backoff; show a non-alarming "try again" message.
Generic failureTOKENIZATION_FAILED, TOKEN_REGISTRATION_FAILED, PAYMENT_FAILED, CHECKOUT_CONTEXT_FETCH_FAILEDShow a generic failure message, log the requestId, and let the user retry.

Never display requestId, httpStatus, or raw details to end users. Log them for your own debugging and support, and show only a clean, friendly message (or your own copy) in the UI.

Next steps

On this page