Error handling

PaygreenJS distinguishes between recoverable errors — issues the buyer can fix themselves (invalid card field, declined card, expired date) — and unexpected errors that interrupt the payment flow (invalid public key, unauthorized domain, network failure).

Recoverable errors are exposed through dedicated events (*_FIELD_ONCHANGE, TOKEN_FAIL, PAYMENT_FAIL), while unexpected failures go through the generic ERROR event.

PaygreenJS surfaces errors through three channels. Each one is meant for a different UX.

You want to…Listen toFires for
Show an inline error under a card fieldPAN_FIELD_ONCHANGE, EXP_FIELD_ONCHANGE, CVV_FIELD_ONCHANGEReal-time field validation (typos, expired date, short CVV…).
Show a banner when card tokenization failsTOKEN_FAILCard declined by the issuer, 3DS rejection, generic tokenize failure.
Show a final "payment failed" screenPAYMENT_FAILThe Payment Order reached a terminal failure status.
Catch unexpected integration/runtime errorsERRORInvalid public key, unauthorized domain, network failure, PSP-side error.

Inline field errors

While the buyer types in a card field, PaygreenJS fires PAN_FIELD_ONCHANGE, EXP_FIELD_ONCHANGE and CVV_FIELD_ONCHANGE. Each event tells you whether the field is valid and, if not, what went wrong and provides a translated error message ready to display.

Event payload

{
  valid:    boolean | null,     // true when valid, false when invalid, null when incomplete
  error?:   string,             // machine-readable error code (see table below)
  message?: string,             // same error, translated in the active language
  // PAN only:
  issuer?:           string,
  availableIssuers?: string[],
  networks?:         string[],
}

event.detail.message is already translated to the language set by lang: in init() or by setLanguage(). If you maintain your own copy, ignore message and switch on error instead.

Error codes

CodeFieldWhen
pan_too_shortPANNumber is shorter than expected for the detected brand.
pan_too_longPANNumber is longer than expected for the detected brand.
invalid_panPANFailed the Luhn check.
cvv_too_shortCVVShorter than 3 digits (or 4 for Amex).
exp_invalid_formatEXPNot in MM/YY format.
exp_expired_dateEXPDate is in the past.

Example — display the translated message

const panError = document.querySelector('#pan-error');
const expError = document.querySelector('#exp-error');
const cvvError = document.querySelector('#cvv-error');

paygreenjs.on(paygreenjs.Events.PAN_FIELD_ONCHANGE, (event) => {
  panError.textContent = event.detail.message ?? '';
});

paygreenjs.on(paygreenjs.Events.EXP_FIELD_ONCHANGE, (event) => {
  expError.textContent = event.detail.message ?? '';
});

paygreenjs.on(paygreenjs.Events.CVV_FIELD_ONCHANGE, (event) => {
  cvvError.textContent = event.detail.message ?? '';
});

The message refreshes automatically if you call paygreenjs.setLanguage().

Tokenization failures

TOKEN_FAIL fires when card tokenization fails (issuer decline, 3DS rejection, unexpected tokenize error, etc.).

paygreenjs.on(paygreenjs.Events.TOKEN_FAIL, (event) => {
  // event.detail = { error, code, message }
  showBanner(event?.detail?.message);

  if (event?.detail?.error === 'tokenize_invalid_card') {
    // Card was refused — ask the buyer to try another card.
  }
});

Possible values

FieldValues
errortokenize_invalid_card  |  tokenize_unauthorized  |  tokenize_unknown_error
codeinvalid_pan  |  invalid_cvv  |  invalid_exp  |  absent
messageTranslated human-readable message.

Terminal payment failure

PAYMENT_FAIL fires when a Payment Order reaches a terminal failure state.

paygreenjs.on(paygreenjs.Events.PAYMENT_FAIL, (event) => {
  console.log(event?.detail?.error?.message);
});

Useful fields available on event?.detail?.error:

  • method — active payment method
  • message — human-readable error message translated to the active language.

Anything else — the ERROR event

paygreenjs.on(paygreenjs.Events.ERROR, (event) => {
  console.error('PaygreenJS error', event.detail);
});

The ERROR event is also emitted when init() fails — for example:

Causeevent.detail.message
Missing #paygreen-containerMissing paygreen-container
Missing public keyYou must provide a valid PayGreen Public Key
Invalid modeInvalid mode type
mode='payment' without paymentOrder.idYou must provide a valid Payment Order ID
mode='payment' without paymentOrder.objectSecretYou must provide the secret attached to the Payment Order
mode='instrument' without paymentMethodInstrument mode require payment method.
Unsupported paymentMethodProvided method is not available
buyer.id missing when requiredBuyer is required for authorized instrument...
Invalid langYou must provide a valid locale : en,fr,de,es,it