Events and Error Handling

Change events, mount failures, tokenize errors, timeouts and element lifecycle rules for the PCI Compliant SDK.

Before You Start

Read the following guides before proceeding:

GuideWhy
PCI Compliant SDKIsolation model and package map
SDK SetupEnvironments, CSP and origin registration

Overview

Every element reports through callbacks and rejected promises. No callback and no rejection ever carries a
card value: events carry validity flags, the detected brand and tokenize results; errors carry a safe
message and, where a backend call was made, its HTTP status.


The Change Event

Collect elements report non-sensitive state while the user types.

onChange: state => {
  state.complete;   // boolean — every field of the profile passes validation
  state.brand;      // 'Visa' | 'MasterCard' | 'unknown'
  state.fields;     // { number: { valid, touched }, … }
}
FieldTypeDescription
completebooleantrue when every field of the profile is valid
brandenumVisa, MasterCard or unknown. Reported by the card-number field
fieldsobjectPer-field { valid, touched }. Keys are the fields of the profile

Use it to enable your submit button and to drive brand-dependent UI. A field that has never been mounted
reports { valid: false, touched: false }.


Field Validation

The frames validate as the user types and render error messages inline, inside the frame, styled by
colorError and localized by strings. Do not re-implement card validation on your page.

Calling a tokenizer while a field is invalid rejects with a PciFrameRequestError whose message starts
with Validation failed. The inline message is already visible to the user, so the typical handler shows
nothing extra for that case:

import { PciFrameRequestError } from '@wirexapp/card-topup-web';

try {
  const result = await topUp.tokenizeTopUp({ billingDetails });
} catch (error) {
  const isFieldValidation =
    error instanceof PciFrameRequestError && error.message.startsWith('Validation failed');
  if (!isFieldValidation) {
    showToast('Failed to add card');
  }
}

The per-field variant reports which field failed: Validation failed — number: <message>,
Validation failed — missing <field> when a sibling field was never mounted, and
Validation failed — invalid <field> when a sibling holds an invalid value.


PciFrameRequestError

Every frame-request failure the frame itself reports — init and tokenize — rejects with this class.

PropertyTypeDescription
messagestringSafe, non-sensitive description: a validation failure, the backend's error message, or a transport failure
statusnumber | undefinedHTTP status of the underlying backend call, where one was made
MessageCauseResolution
Validation failed — …A field is empty or invalid at tokenize timeShow nothing extra; the inline message is already visible
Backend error text, with statusTokenization rejected by WirexSurface a generic failure and let the user retry
Network errorThe frame could not reach WirexSurface a retry action
Card service is not configuredFrame service misconfigurationReport it to your Wirex integration contact

The class is re-exported as a value by every capability package and by @wirexapp/card-react, so
instanceof works from whichever package you import.


Mount Failures

field(name).mount(container) and mount(container) reject when the frame document cannot load or refuses
to initialize. These reject with a plain Error, not a PciFrameRequestError.

try {
  await topUp.field('number').mount(el);
} catch {
  showToast('Failed to load the secure card form');
}
MessageCauseResolution
PCI frame did not become ready in timeThe parent origin is not registered, the environment is wrong, the network failed, or the loader and frame protocol versions differVerify the registered origins and the environment value; align every @wirexapp/card-* package on one version
PCI frame is not mountedA tokenize call was made before mounting or after destroy()Create a new element
PCI frame request timed outNo response to init or tokenize within 30 secondsSurface a retry action
PCI frame destroyeddestroy() ran while a request was in flightExpected during teardown. Ignore it
PCI SDK: unknown environment "<value>"environment is not dev, uat or prodCorrect the config

An unregistered parent origin is the most common mount failure. The browser blocks the frame through
frame-ancestors, the iframe renders empty, and the ready handshake never completes — so the symptom is a
timeout, not a CSP error in your own console.

PhaseLimit
Frame ready handshake10 seconds
Frame request — init or tokenize30 seconds

Reveal State

The reveal element reports its lifecycle through onStateChange.

onStateChange: ({ status, errorMessage }) => {
  // status: 'loading' | 'ready' | 'error'
}
StatusMeaning
loadingThe frame verified its init and started fetching
readyAt least one requested row loaded
errorEvery requested fetch failed. errorMessage is safe to display

error covers a consumed or expired actionToken, an unknown card id, a card status that does not permit
the operation, and backend failures. A partial failure reports ready with an em dash in the failed rows —
see Reveal Card Details.


Lifecycle Rules

  • Call destroy() on every element when its view unmounts. It removes the iframes and the message
    listeners.
  • Elements are single-use. After destroy(), create a new element rather than remounting the old one.
  • Field iframes report their own height and the SDK sizes them. Width and placement come from your
    containers.
  • Appearance and strings are read at mount. Re-theming requires a new element.
  • In React these rules are handled by the components — see React Bindings.

What Never Reaches Your Page

  • The PAN, CVV and expiry as typed by the user, and the values fetched by a reveal element
  • The frames' API endpoints, which the frame service injects server-side
  • Clipboard content copied inside a reveal frame. onCopied carries the field name and nothing else
  • Any event payload beyond validity flags, the detected brand, and tokenize results — cardId or
    externalCardId, brand, BIN, last 4 and expiry month and year

Did this page help you?