---
title: Field Validation Rules
description: Default validation behavior, required properties, and constraints for each ObjectStack field type
---

# Field Validation Rules

Every ObjectStack field type has built-in validation behavior that runs automatically at the schema level. This reference documents the **default constraints**, **required properties**, and **validation semantics** for each of the 48 field types.

<Callout type="info">
**Source:** `packages/spec/src/data/field.zod.ts`  
**Import:** `import { FieldSchema, FieldType } from '@objectstack/spec/data'`
</Callout>

---

## Universal Field Constraints

These properties apply to **all** field types and are validated by the base `FieldSchema`:

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `name` | `string` | — | Must match `^[a-z_][a-z0-9_]*$` (snake_case) |
| `label` | `string` | — | Human-readable display name |
| `type` | `FieldType` | — | Must be one of the 48 defined types |
| `required` | `boolean` | `false` | Rejects `null`/`undefined` at runtime when `true` |
| `unique` | `boolean` | `false` | Enforces database-level uniqueness constraint |
| `multiple` | `boolean` | `false` | Stores value as array (applicable for select, lookup, file, image) |
| `hidden` | `boolean` | `false` | Excluded from default UI rendering |
| `readonly` | `boolean` | `false` | Blocks user edits in UI forms |
| `sortable` | `boolean` | `true` | Whether field appears in list view sort options |
| `index` | `boolean` | `false` | Creates standard database index |
| `externalId` | `boolean` | `false` | Marks field as external ID for upsert operations |
| `auditTrail` | `boolean` | `false` | Tracks all changes with user and timestamp |
| `visibleWhen` | `string \| Expression` | — | CEL predicate; field is shown only when `TRUE` |
| `readonlyWhen` | `string \| Expression` | — | CEL predicate; field is read-only when `TRUE` |
| `requiredWhen` | `string \| Expression` | — | CEL predicate; field is required when `TRUE` |
| `conditionalRequired` | `string \| Expression` | — | Deprecated alias of `requiredWhen` |

---

## Text Types

### `text`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `maxLength` | `number` | — | Rejects values exceeding character count |
| `minLength` | `number` | — | Rejects values below character count |
| `format` | `string` | — | Validates against format pattern (e.g., regex) |
| `caseSensitive` | `boolean` | — | Controls case-sensitivity in uniqueness checks |

**Default constraints:** None. Unbounded text unless `maxLength` is set.

### `textarea`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `maxLength` | `number` | — | Rejects values exceeding character count |
| `minLength` | `number` | — | Rejects values below character count |

**Default constraints:** None. Multi-line text with no length limit by default.

### `email`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `format` | `string` | `email` | Validates RFC 5322 email format |
| `caseSensitive` | `boolean` | — | Controls case-sensitivity in uniqueness checks |

**Default constraints:** Must conform to valid email format.

### `url`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `format` | `string` | `url` | Validates URL format (protocol required) |

**Default constraints:** Must be a valid URL with protocol prefix.

### `phone`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `format` | `string` | `phone` | Validates phone number format |

**Default constraints:** Accepts E.164 and common national formats.

### `password`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `maxLength` | `number` | — | Maximum password length |
| `minLength` | `number` | — | Minimum password length |

**Default constraints:** Value is never returned in read operations. Stored encrypted.

---

## Rich Content Types

### `markdown`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `maxLength` | `number` | — | Character limit on raw markdown source |

**Default constraints:** Accepts valid Markdown syntax. No length limit by default.

### `html`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `maxLength` | `number` | — | Character limit on raw HTML source |

**Default constraints:** HTML content is sanitized to prevent XSS. No length limit by default.

### `richtext`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `maxLength` | `number` | — | Character limit on serialized content |

**Default constraints:** Stored as structured rich text (e.g., ProseMirror/Tiptap JSON). Sanitized on save.

---

## Number Types

### `number`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `min` | `number` | — | Rejects values below minimum |
| `max` | `number` | — | Rejects values above maximum |
| `precision` | `number` | — | Total number of digits allowed |
| `scale` | `number` | — | Number of decimal places |

**Default constraints:** Any valid number. No range or precision limits by default.

### `currency`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `min` | `number` | — | Minimum monetary value |
| `max` | `number` | — | Maximum monetary value |
| `currencyConfig.precision` | `number` | `2` | Decimal places (0–10) |
| `currencyConfig.currencyMode` | `enum` | `dynamic` | `dynamic` (user-selectable) or `fixed` (single currency) |
| `currencyConfig.defaultCurrency` | `string` | `CNY` | 3-character currency code (ISO 4217 or crypto) |

**Default constraints:** Stored as `{ value, currency }` pair. Precision defaults to 2 decimal places.

### `percent`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `min` | `number` | — | Minimum percentage value |
| `max` | `number` | — | Maximum percentage value |
| `precision` | `number` | — | Total digits |
| `scale` | `number` | — | Decimal places |

**Default constraints:** Stored as decimal (e.g., `0.85` for 85%). No range limit by default.

---

## Date & Time Types

### `date`

**Required props:** None.  
**Default constraints:** Validates ISO 8601 date format (`YYYY-MM-DD`). No range restrictions.

### `datetime`

**Required props:** None.  
**Default constraints:** Validates ISO 8601 datetime format (`YYYY-MM-DDTHH:mm:ssZ`). Stored in UTC.

### `time`

**Required props:** None.  
**Default constraints:** Validates ISO 8601 time format (`HH:mm:ss`). 24-hour format.

---

## Boolean Types

### `boolean`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `defaultValue` | `boolean` | — | Initial value when field is empty |

**Default constraints:** Only accepts `true` or `false`. Renders as checkbox.

### `toggle`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `defaultValue` | `boolean` | — | Initial value when field is empty |

**Default constraints:** Identical validation to `boolean`. Distinct UI — renders as toggle switch.

---

## Selection Types

### `select`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `options` | `SelectOption[]` | — | **Required.** Static option list |
| `defaultValue` | `string` | — | Must match an option `value` |

**Option validation:** Each option `value` must be lowercase (`^[a-z_][a-z0-9_]*$`).

### `multiselect`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `options` | `SelectOption[]` | — | **Required.** Static option list |

**Default constraints:** Stores array of selected option values. Each value validated against options.

### `radio`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `options` | `SelectOption[]` | — | **Required.** Static option list |

**Default constraints:** Single-value selection. Same validation as `select` with radio button UI.

### `checkboxes`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `options` | `SelectOption[]` | — | **Required.** Static option list |

**Default constraints:** Multi-value selection. Same validation as `multiselect` with checkbox group UI.

---

## Relational Types

### `lookup`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `reference` | `string` | — | **Required.** Target object name |
| `referenceFilters` | `string[]` | — | Filter expressions for lookup dialogs |
| `deleteBehavior` | `enum` | `set_null` | `set_null`, `cascade`, or `restrict` |
| `multiple` | `boolean` | `false` | Allow multiple references |

**Default constraints:** Validates that referenced record exists. Foreign key integrity enforced.

### `master_detail`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `reference` | `string` | — | **Required.** Parent object name |
| `deleteBehavior` | `enum` | `set_null` | Typically `cascade` for master-detail |
| `writeRequiresMasterRead` | `boolean` | — | Require read access to master record |

**Default constraints:** Enforces parent-child ownership. Child records cascade-delete with parent by convention.

### `tree`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `reference` | `string` | — | **Required.** Self-referencing object name |

**Default constraints:** Self-referencing lookup for hierarchical structures. Prevents circular references.

---

## Media Types

### `image`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `fileAttachmentConfig` | `object` | — | File size, type, and image dimension rules |
| `multiple` | `boolean` | `false` | Allow multiple image uploads |

**Default constraints:** Accepts common image MIME types. Optional dimension and thumbnail validation via `fileAttachmentConfig`.

### `file`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `fileAttachmentConfig` | `object` | — | Full file upload validation config |
| `multiple` | `boolean` | `false` | Allow multiple file uploads |

**Default constraints:** Accepts any file type unless restricted. Supports virus scanning, size limits, and type restrictions.

```typescript
// File field with validation
{
  name: 'contract_pdf',
  label: 'Contract',
  type: 'file',
  fileAttachmentConfig: {
    maxSize: 10485760,           // 10MB
    allowedTypes: ['.pdf', '.docx'],
    virusScan: true,
    virusScanProvider: 'clamav'
  }
}
```

### `avatar`

**Default constraints:** Single image upload. Typically constrained to square aspect ratio and small file sizes.

### `video`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `fileAttachmentConfig` | `object` | — | File size and type restrictions |

**Default constraints:** Accepts common video MIME types. Size limits recommended via `fileAttachmentConfig`.

### `audio`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `fileAttachmentConfig` | `object` | — | File size and type restrictions |

**Default constraints:** Accepts common audio MIME types. Size limits recommended via `fileAttachmentConfig`.

---

## Computed & System Types

### `formula`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `expression` | `string` | — | **Required.** Formula expression |
| `dependencies` | `string[]` | — | Fields this formula depends on |
| `cached` | `object` | — | Caching configuration with TTL and invalidation triggers |

**Default constraints:** Read-only. Value computed at runtime from `expression`. Not directly writable.

```typescript
{
  name: 'full_name',
  label: 'Full Name',
  type: 'formula',
  expression: 'CONCAT(first_name, " ", last_name)',
  dependencies: ['first_name', 'last_name'],
  cached: { enabled: true, ttl: 3600, invalidateOn: ['first_name', 'last_name'] }
}
```

### `summary`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `summaryOperations` | `object` | — | **Required.** Roll-up definition |
| `summaryOperations.object` | `string` | — | Child object to aggregate |
| `summaryOperations.field` | `string` | — | Field to aggregate |
| `summaryOperations.function` | `enum` | — | `count`, `sum`, `min`, `max`, or `avg` |

**Default constraints:** Read-only. Value computed from child records. Only valid on master objects.

### `autonumber`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `autonumberFormat` | `string` | — | Display format pattern (e.g., `CASE-{0000}`) |

**Default constraints:** Read-only. Auto-incremented. Cannot be manually set after creation.

---

## Enhanced Types

### `location`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `displayMap` | `boolean` | — | Show map widget in UI |
| `allowGeocoding` | `boolean` | — | Enable address-to-coordinate conversion |

**Default constraints:** Stored as `{ latitude, longitude, altitude?, accuracy? }`. Latitude: -90 to 90. Longitude: -180 to 180.

### `address`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `addressFormat` | `enum` | — | `us`, `uk`, or `international` |

**Default constraints:** Stored as structured object with `street`, `city`, `state`, `postalCode`, `country`, `countryCode`, `formatted`.

### `code`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `language` | `string` | — | Programming language for syntax highlighting |
| `theme` | `string` | — | Editor theme (e.g., `dark`, `monokai`) |
| `lineNumbers` | `boolean` | — | Show line numbers in editor |

**Default constraints:** Stored as plain text. Language used for UI syntax highlighting only.

### `json`

**Default constraints:** Must be valid JSON. Parsed and validated on save.

### `color`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `colorFormat` | `enum` | — | `hex`, `rgb`, `rgba`, or `hsl` |
| `allowAlpha` | `boolean` | — | Allow transparency channel |
| `presetColors` | `string[]` | — | Predefined color swatches |

**Default constraints:** Validated against the specified `colorFormat`. Defaults to hex if not specified.

### `rating`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `maxRating` | `number` | `5` | Maximum rating value |
| `allowHalf` | `boolean` | — | Allow half-step increments |

**Default constraints:** Integer between 0 and `maxRating`. Half-steps allowed when `allowHalf` is true.

### `slider`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `min` | `number` | — | Minimum slider value |
| `max` | `number` | — | Maximum slider value |
| `step` | `number` | `1` | Step increment |
| `showValue` | `boolean` | — | Display current value |
| `marks` | `Record<string, string>` | — | Custom labels at specific values |

**Default constraints:** Numeric value between `min` and `max` in `step` increments.

### `signature`

**Default constraints:** Stored as base64-encoded image data. Immutable after creation in most workflows.

### `qrcode`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `barcodeFormat` | `enum` | — | `qr`, `ean13`, `ean8`, `code128`, `code39`, `upca`, `upce` |
| `qrErrorCorrection` | `enum` | — | `L` (7%), `M` (15%), `Q` (25%), `H` (30%) — only for `qr` format |
| `displayValue` | `boolean` | — | Show human-readable value below code |
| `allowScanning` | `boolean` | — | Enable camera scanning input |

**Default constraints:** `qrErrorCorrection` only applies when `barcodeFormat` is `qr`. Value validated against barcode format rules.

### `progress`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `min` | `number` | — | Minimum value (typically `0`) |
| `max` | `number` | — | Maximum value (typically `100`) |

**Default constraints:** Numeric value rendered as a progress bar. Usually 0–100.

### `tags`

**Default constraints:** Stored as array of strings. Each tag is trimmed and deduplicated.

---

## AI/ML Types

### `vector`

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `vectorConfig.dimensions` | `number` | — | **Required.** Vector size (1–10,000) |
| `vectorConfig.distanceMetric` | `enum` | `cosine` | `cosine`, `euclidean`, `dotProduct`, `manhattan` |
| `vectorConfig.normalized` | `boolean` | `false` | Whether vectors are unit-length |
| `vectorConfig.indexed` | `boolean` | `true` | Create vector index for similarity search |
| `vectorConfig.indexType` | `enum` | — | `hnsw`, `ivfflat`, or `flat` |

**Default constraints:** Must be a numeric array of exactly `dimensions` length. Indexed by default for fast similarity search.

```typescript
{
  name: 'content_embedding',
  label: 'Content Embedding',
  type: 'vector',
  vectorConfig: {
    dimensions: 1536,
    distanceMetric: 'cosine',
    indexed: true,
    indexType: 'hnsw'
  }
}
```

---

## Data Quality Rules

Any field can optionally include `dataQuality` rules for governance and monitoring:

| Property | Type | Default | Validation Behavior |
|:---|:---|:---|:---|
| `dataQuality.uniqueness` | `boolean` | `false` | Enforce unique values across all records |
| `dataQuality.completeness` | `number` | `0` | Minimum ratio of non-null values (0–1) |
| `dataQuality.accuracy.source` | `string` | — | Reference data source for validation |
| `dataQuality.accuracy.threshold` | `number` | — | Minimum accuracy threshold (0–1) |

```typescript
{
  name: 'social_security',
  label: 'SSN',
  type: 'text',
  dataQuality: {
    uniqueness: true,
    completeness: 0.95,
    accuracy: { source: 'government_db', threshold: 0.98 }
  }
}
```

---

## Security & Compliance Properties

Fields supporting sensitive data can leverage encryption and masking:

| Property | Type | Default | Description |
|:---|:---|:---|:---|
| `encryptionConfig` | `EncryptionConfig` | — | Field-level encryption (GDPR/HIPAA/PCI-DSS) |
| `maskingRule` | `MaskingRule` | — | Data masking rules for PII protection |
| `auditTrail` | `boolean` | `false` | Track all changes with user and timestamp |

---

## Quick Validation Summary

| Field Type | Required Props | Key Constraints |
|:---|:---|:---|
| `text` | — | `maxLength`, `minLength`, `format` |
| `textarea` | — | `maxLength`, `minLength` |
| `email` | — | RFC 5322 email format |
| `url` | — | Valid URL with protocol |
| `phone` | — | E.164 / national format |
| `password` | — | Stored encrypted, never returned |
| `markdown` | — | `maxLength` |
| `html` | — | Sanitized, `maxLength` |
| `richtext` | — | Sanitized, `maxLength` |
| `number` | — | `min`, `max`, `precision`, `scale` |
| `currency` | — | `currencyConfig` (precision, mode, code) |
| `percent` | — | `min`, `max`, stored as decimal |
| `date` | — | ISO 8601 date |
| `datetime` | — | ISO 8601 datetime, UTC |
| `time` | — | ISO 8601 time, 24h |
| `boolean` | — | `true` / `false` only |
| `toggle` | — | `true` / `false` only |
| `select` | `options` | Option values must be lowercase snake_case |
| `multiselect` | `options` | Array of valid option values |
| `radio` | `options` | Single value from options |
| `checkboxes` | `options` | Array of valid option values |
| `lookup` | `reference` | Foreign key integrity |
| `master_detail` | `reference` | Cascade delete, ownership |
| `tree` | `reference` | Self-referencing, no circular refs |
| `image` | — | `fileAttachmentConfig` for dimensions |
| `file` | — | `fileAttachmentConfig` for restrictions |
| `avatar` | — | Single image, typically square |
| `video` | — | `fileAttachmentConfig` for size limits |
| `audio` | — | `fileAttachmentConfig` for size limits |
| `formula` | `expression` | Read-only, computed at runtime |
| `summary` | `summaryOperations` | Read-only, roll-up from children |
| `autonumber` | — | Read-only, auto-incremented |
| `location` | — | Lat: -90–90, Lng: -180–180 |
| `address` | — | Structured object, `addressFormat` |
| `code` | — | Plain text, `language` for highlighting |
| `json` | — | Must be valid JSON |
| `color` | — | Validated against `colorFormat` |
| `rating` | — | 0 to `maxRating` (default 5) |
| `slider` | — | `min` to `max` in `step` increments |
| `signature` | — | Base64 image, typically immutable |
| `qrcode` | — | Format-specific validation |
| `progress` | — | Numeric, typically 0–100 |
| `tags` | — | String array, trimmed, deduplicated |
| `vector` | `vectorConfig` | Numeric array of exact `dimensions` length |
