# `ValidationError`

Client-side validation error type for card field form validation. Unlike [`RevolutCheckoutError`](/docs/sdks/merchant-web-sdk/types/revolut-checkout-error) which occurs during payment processing and is handled via `onError` callbacks, `ValidationError` occurs during real-time form field validation in the card field widget and is handled via `onValidation` callbacks. Validation error messages are automatically localised based on the widget's locale setting.

## Type signature

```typescript
interface ValidationError extends Error {
  name: 'Validation'
  type: ValidationErrorType
  message: string
}

type ValidationErrorType =
  | 'validation.card.number.incomplete'
  | 'validation.card.number.invalid'
  | 'validation.card.number.required'
  | 'validation.card.expiry.expired'
  | 'validation.card.expiry.incomplete'
  | 'validation.card.expiry.required'
  | 'validation.card.cvv.invalid'
  | 'validation.card.cvv.required'
  | 'validation.card.type.invalid'
  | 'validation.postcode.invalid'
  | 'validation.postcode.country-invalid'
  | 'validation.postcode.required'
  | 'validation.email.incomplete'
  | 'validation.email.invalid'
  | 'validation.email.required'
  | 'validation.phone.code.required'
  | 'validation.phone.number.invalid'
  | 'validation.phone.number.required'
```

## Properties

| Property  | Description                                                         | Type                  | Required |
| --------- | ------------------------------------------------------------------- | --------------------- | -------- |
| `name`    | Always set to `'Validation'` to identify validation errors          | `'Validation'`        | Yes      |
| `type`    | Specific validation error type identifier                           | `ValidationErrorType` | Yes      |
| `message` | Human-readable error description (localised based on widget locale) | `string`              | Yes      |

## Validation error types

### Card number errors

| Error type                          | Description                         | User action                    |
| ----------------------------------- | ----------------------------------- | ------------------------------ |
| `validation.card.number.incomplete` | Card number is partially entered    | Complete card number           |
| `validation.card.number.invalid`    | Card number fails format validation | Check card number and re-enter |
| `validation.card.number.required`   | Card number field is empty          | Enter card number              |
| `validation.card.type.invalid`      | Card type not supported by merchant | Try a different card           |

### Card expiry errors

| Error type                          | Description                         | User action                  |
| ----------------------------------- | ----------------------------------- | ---------------------------- |
| `validation.card.expiry.expired`    | Card expiration date is in the past | Use a different card         |
| `validation.card.expiry.incomplete` | Expiry date is partially entered    | Complete expiry date (MM/YY) |
| `validation.card.expiry.required`   | Expiry date field is empty          | Enter expiry date            |

### CVV/CVC errors

| Error type                     | Description                    | User action                                  |
| ------------------------------ | ------------------------------ | -------------------------------------------- |
| `validation.card.cvv.invalid`  | CVV/CVC code format is invalid | Check CVV (3-4 digits on back/front of card) |
| `validation.card.cvv.required` | CVV/CVC field is empty         | Enter CVV code                               |

### Postcode errors

| Error type                            | Description                                  | User action                                |
| ------------------------------------- | -------------------------------------------- | ------------------------------------------ |
| `validation.postcode.invalid`         | Postcode format doesn't match country format | Check postcode format for selected country |
| `validation.postcode.country-invalid` | Postcode doesn't match selected country      | Verify country and postcode match          |
| `validation.postcode.required`        | Postcode field is empty                      | Enter postcode/ZIP code                    |

### Email errors

| Error type                    | Description                | User action                                   |
| ----------------------------- | -------------------------- | --------------------------------------------- |
| `validation.email.incomplete` | Email is partially entered | Complete email address                        |
| `validation.email.invalid`    | Email format is invalid    | Check email format (e.g., `user@example.com`) |
| `validation.email.required`   | Email field is empty       | Enter email address                           |

### Phone errors

| Error type                         | Description                            | User action               |
| ---------------------------------- | -------------------------------------- | ------------------------- |
| `validation.phone.code.required`   | Country code missing from phone number | Select country code       |
| `validation.phone.number.invalid`  | Phone number format is invalid         | Check phone number format |
| `validation.phone.number.required` | Phone number field is empty            | Enter phone number        |

## Usage

### Basic validation handling

```typescript
import RevolutCheckout from '@revolut/checkout'
import type { ValidationError } from '@revolut/checkout'

const instance = await RevolutCheckout(orderToken, 'prod')

const cardField = instance.createCardField({
  target: document.getElementById('card-field'),

  onValidation: (errors: ValidationError[]) => {
    if (errors.length === 0) {
      // All fields valid
      console.log('Card details valid')
    } else {
      // Show validation errors
      console.log('Validation errors:', errors)
      displayErrors(errors)
    }
  },
})
```

### Displaying field-specific errors

```typescript
import type { ValidationError } from '@revolut/checkout'

function displayErrors(errors: ValidationError[]): void {
  errors.forEach((error) => {
    // Check error type prefix to determine which field has the error
    if (error.type.startsWith('validation.card.number')) {
      showFieldError('card-number', error.message)
    } else if (error.type.startsWith('validation.card.expiry')) {
      showFieldError('card-expiry', error.message)
    } else if (error.type.startsWith('validation.card.cvv')) {
      showFieldError('card-cvv', error.message)
    } else if (error.type.startsWith('validation.postcode')) {
      showFieldError('postcode', error.message)
    } else if (error.type.startsWith('validation.email')) {
      showFieldError('email', error.message)
    } else if (error.type.startsWith('validation.phone')) {
      showFieldError('phone', error.message)
    }
  })
}
```

## Usage scenarios

The SDK provides validation errors via the `onValidation` callback, which fires in real-time as the customer interacts with the card field widget. Common scenarios include:

- **Submit button control**: Disable the submit button when `errors.length > 0` to prevent submission of invalid data
- **Field-specific error display**: Check the `error.type` prefix to determine which field has the error and display the message near that field
- **Error prioritisation**: Filter errors by type suffix (`.required`, `.invalid`, `.incomplete`) to show critical errors first
- **Localised messages**: Use `error.message` directly as it's automatically localised based on the widget's `locale` setting
- **Custom error messages**: Override the SDK's error messages by mapping `error.type` to custom messages
- **Analytics tracking**: Log validation errors to track which fields cause the most issues for customers

## See also

- [RevolutCheckoutError](/docs/sdks/merchant-web-sdk/types/revolut-checkout-error) - Payment processing errors
- [Card field](/docs/sdks/merchant-web-sdk/payment-methods/card-field) - Card field widget with validation