Skip to main content
validate is a custom synchronous callback that decides whether an element’s current value is acceptable. It runs on every change (debounced), on blur (synchronous), and at submit time (synchronous). Providing validate opts the element fully out of built-in validation. The callback owns the entire validity contract.

Signature

  • Return null to signal the value is valid.
  • Return any non-empty string to surface a FieldError with code: 'custom' and the returned string as message.
The value shape matches what appears on onChange.value: card does not accept validate. submitButton, applePay, googlePay, and checkout also do not.

Example

Precedence: validate disables built-ins

When validate is supplied, the SDK skips all built-in checks for that element:
  • The zod format schema (email format, address atom formats, and so on).
  • Provider-level validity checks (for example, the phone element’s E.164 check).
  • The built-in required empty check.
The callback receives every value, including null for empty inputs. This is intentional: “I provided validate, so I own this.” To keep the built-in checks and layer business rules on top, leave validate unset and gate your business logic elsewhere (server-side, or inside your own onChange handler).

Debouncing

The callback runs debounced. The default delay is 250 ms. Tune it per-instance:
The debouncer is latest-wins: rapid keystrokes coalesce into one trailing-edge call. Pending callbacks flush synchronously on blur and on submit(), so error snapshots are current when the shopper tabs away or submits.

Multi-field elements

For billingAddress, shippingAddress, and bank, the callback receives the whole-shape value:
The returned message routes to the element-level error slot (rendered above the atoms). Per-atom custom validators are not exposed. Inspect whichever atoms you care about inside the whole-shape callback; use the built-in per-atom required and format checks for atom-keyed errors.

Bank

validate on bank runs in manual mode only. In address-lookup mode, the SDK’s own lookup owns validity timing and skips the callback.

Async validation

validateAsync is reserved for a future release. Attempting to set it fails type-check today.

FieldError from validate

Read errors from onChange.errors (live) or onError.fieldErrors (submit time).

See also

Last modified on July 17, 2026