# Field validation

Field validation ensures that the data collected in your flows meets defined formatting, business, and quality requirements. Formsort supports both built-in and custom validators.

***

### Built-in Validators

Formsort includes many default validators for common input types:

* **Number questions**: Enforce min/max value, integer constraints, and step intervals.
* **Email fields**: Automatically validate email formatting.
* **Text fields**: Can be configured with length or character restrictions.

These default validators cover the most common cases. For advanced use cases, **custom validators** are available.

***

### Custom Validators (Enterprise Only)

Custom validators allow you to define your own validation logic using regular expressions, custom code, or asynchronous API calls. They are defined at the **workspace** level and can be reused across flows.

<figure><img src="/files/OkpodK9oqKRaBvQ9OpUu" alt=""><figcaption><p>Custom validators are defined at the workspace level</p></figcaption></figure>

### Defining Custom Validators

Custom validators are composed of two main parts:

#### **1. Validator Metadata**

Metadata includes:

* **Name** and **description** (used for identification in the Studio)
* **Answer type** (e.g., string, number, object) – this controls which questions or variables can use the validator

<div align="left"><figure><img src="/files/v7EG1B8p3jHgJHX8ScdT" alt="" width="281"><figcaption></figcaption></figure></div>

{% hint style="info" %}
Ensure the validator's answer type matches the target question’s type—e.g., string validators won't apply to number fields.
{% endhint %}

#### **2. Validation Rules**

Validators can contain multiple rules. Each rule must pass for the value to be considered valid.

<div align="left"><figure><img src="/files/hQeFnMqZacP6Ze0VYY3y" alt="" width="275"><figcaption></figcaption></figure></div>

#### **Rule Severity**

* **Error**: Blocking. The responder cannot proceed unless the input is corrected.

<div align="left" data-full-width="false"><figure><img src="/files/5IOPwlZ7Eovg1lMnnvga" alt="" width="375"><figcaption></figcaption></figure></div>

* **Warning**: Non-blocking. The responder is alerted, but may choose to proceed.

<div align="left"><figure><img src="/files/WX8tiWlluvTjXDqG3aj8" alt="" width="375"><figcaption></figcaption></figure></div>

### Regular expression rules

Regular expressions (`regex`) are available only for string inputs. You can create rules for inputs that **must match** or **must not match** a given pattern.

**Example: Twitter Handle Validator**

| Rule Type          | Pattern           | Error Message                                                                   |
| ------------------ | ----------------- | ------------------------------------------------------------------------------- |
| **Must match**     | `^[a-zA-Z0-9_]+$` | A username can only contain alphanumeric characters (A–Z, 0–9) and underscores. |
| **Must match**     | `^.{1,15}$`       | Handles must be between 1 and 15 characters long.                               |
| **Must not match** | \`Twitter         | Admin\` (case-insensitive)                                                      |

{% hint style="info" %}
Rules 1 and 2 (and probably 3) can be collapsed into a single regular expression that checks for both, which would be  `^[a-zA-Z0-9_]{1,15}$.`

Splitting out rules is preferred, as it allows for more targeted error messages. We can warn users with a specific message when they have an invalid character OR their handle is too long, making it easier to see what's wrong with the input and correct it.
{% endhint %}

<div align="left"><figure><img src="/files/56GUn85hViaSjpNGSMmz" alt=""><figcaption></figcaption></figure></div>

### Custom code rules

For more flexibility, you can write custom validation functions using TypeScript.

**Example:**

```typescript
function myFunction(value: string): ValidatorResult | undefined { // readonly line
  if (value.match(/admin|twitter/i)) {
    return {
      severity: 'error',
      message: 'Handle cannot contain the words "admin" or "twitter"'
    }
  }
  if (value.match(/[^a-zA-Z0-9_]/)) {
    return {
      severity: 'error',
      message: 'A username can only contain alphanumeric characters (letters A-Z, numbers 0-9) with the exception of underscores.'
    }
  }
  if (value.length > 15) {
    return {
      severity: 'error',
      message: 'Usernames cannot be more than 15 characters long'
    }
  }
}
```

<figure><img src="/files/FI05CcrP6ZyaOIGWFKLp" alt=""><figcaption><p>Writing a custom code validator</p></figcaption></figure>

* Return a `ValidatorResult` when the input is invalid.
* Return `undefined` when input passes validation.

{% hint style="info" %}
Note: Only the first validation error is shown—custom functions exit at the first `return`.
{% endhint %}

### Async custom code

Enable **async** mode to fetch data from external sources during validation using `await`.

**Example (hypothetical Twitter handle check):**

```typescript
function myFunction(value: string): Promise<ValidatorResult | undefined> { // readonly line
  const res = await fetch('https://api.twitter.com/check-handle');
  const handleInfo = await res.json();
  if (handleInfo.taken) {
    return {
      severity: 'error',
      message: 'This handle has already been registered'
    }
  }
}
```

{% hint style="info" %}
You must enable the **Async** checkbox in the validator configuration.
{% endhint %}

### Testing validators

Use the **Test** tab to try out inputs and preview validation behavior:

* **Regex rules**: All rules are evaluated in parallel. Violations for each rule are shown independently.
* **Custom functions**: Only the first failed check is returned.

**Examples:**

<figure><img src="/files/JYZGGGrLqoNuaWJrpUXi" alt=""><figcaption><p>Rule 1 being enforced</p></figcaption></figure>

<figure><img src="/files/Y668gaDphxAtTp8wzpeu" alt=""><figcaption><p>Rule 2 being enforced</p></figcaption></figure>

<figure><img src="/files/a8B4PjE0ICHOlCo4piD2" alt=""><figcaption><p>Rule 3 being enforced</p></figcaption></figure>

Using the Regular Experssion UI (described [above](#regular-expression-rules)) has the added benefit of evaluating all rules concurrently, and outputting an error message for each rule that is violated:&#x20;

<figure><img src="/files/8kyGQP6yDdhhYx7x8g0E" alt=""><figcaption><p>All rules being enforced at once</p></figcaption></figure>

***

### Using custom validators in a flow

Once created, custom validators become selectable in Question settings (if the question’s data type matches the validator).

<figure><img src="/files/AAvpe6k5blxat8ApGn9T" alt=""><figcaption><p>Picking a validator within the content editor</p></figcaption></figure>

***

### Updating custom validators

You can modify validators at any time. However:

* **Flows using the validator need to be redeployed to pick up changes.**
* Use the **Show usages** option to view which flows depend on a validator.

<figure><img src="/files/0SVRDQwXIq83WQj1kMEx" alt=""><figcaption></figcaption></figure>

### Deleting Validators

Custom validators can be deleted from the validator list.

* **Flows already using the validator will continue to function.**
* Deleted validators will no longer be available to assign to new questions or answers.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.formsort.com/field-validation.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
