Validation utilities help you validate documents, work with validation rules, and handle validation errors in Sanity Studio.
validateDocument
Validate a document against its schema and custom rules.
import {validateDocument} from 'sanity'
const result = await validateDocument({
document,
workspace,
getClient,
})
Current workspace configuration
getClient
(config: SourceClientOptions) => SanityClient
required
Function to get a configured Sanity client
Schema to validate against (defaults to workspace schema)
maxCustomValidationConcurrency
Maximum concurrent custom validation functions. Default: 5
Maximum concurrent fetch requests during validation. Default: 25
Array of validation markerslevel
'error' | 'warning' | 'info'
Severity level
Field path where the issue occurs
Nested validation details
Example
import {validateDocument, useWorkspace, useSource} from 'sanity'
import {useState} from 'react'
import {Button, Card, Stack, Text} from '@sanity/ui'
function DocumentValidator({document}: {document: SanityDocument}) {
const workspace = useWorkspace()
const source = useSource()
const [markers, setMarkers] = useState([])
const [validating, setValidating] = useState(false)
const validate = async () => {
setValidating(true)
const result = await validateDocument({
document,
workspace,
getClient: source.getClient,
})
setMarkers(result)
setValidating(false)
}
return (
<Stack space={3}>
<Button onClick={validate} loading={validating}>
Validate Document
</Button>
{markers.length > 0 && (
<Card padding={3} tone="critical">
<Stack space={2}>
{markers.map((marker, i) => (
<Text key={i} size={1}>
{marker.level}: {marker.message}
</Text>
))}
</Stack>
</Card>
)}
</Stack>
)
}
validateDocumentWithReferences
Validate a document including reference validation.
import {validateDocumentWithReferences} from 'sanity'
const {validation, referencedDocuments} = await validateDocumentWithReferences({
document,
workspace,
getClient,
})
Validation resultWhether validation is in progress
Whether there are error-level markers
Whether there are warning-level markers
Documents referenced by the validated document
useValidationStatus
Hook to observe document validation status:
import {useValidationStatus} from 'sanity'
function ValidationIndicator({documentId, documentType}: Props) {
const {isValidating, markers} = useValidationStatus(documentId, documentType)
if (isValidating) return <Spinner />
const errors = markers.filter(m => m.level === 'error')
return (
<Badge tone={errors.length > 0 ? 'critical' : 'positive'}>
{errors.length > 0 ? `${errors.length} errors` : 'Valid'}
</Badge>
)
}
Current validation statusWhether validation is in progress
Whether there are warnings
Rule
Validation rule builder:
import {Rule} from 'sanity'
export default {
name: 'article',
type: 'document',
fields: [
{
name: 'title',
type: 'string',
validation: (Rule: Rule) => Rule.required().min(10).max(100),
},
{
name: 'email',
type: 'string',
validation: (Rule: Rule) => Rule.email(),
},
],
}
Validation Methods
Exact length (for arrays and strings)
Validate against regex patternRule.regex(/^[A-Z]/, {name: 'uppercase', invert: false})
Validate as URIRule.uri({scheme: ['http', 'https']})
Custom validation functionRule.custom((value) => {
if (value && value.includes('badword')) {
return 'Cannot contain bad words'
}
return true
})
Set custom error messageRule.required().error('Title is required')
Set as warning instead of errorRule.min(10).warning('Title should be at least 10 characters')
inferFromSchema
Infer validation rules from schema:
import {inferFromSchema} from 'sanity'
const rules = inferFromSchema(schema, schemaType)
Inferred validation rules
ValidationContext
Context available to custom validation functions:
import {type ValidationContext} from 'sanity'
Rule.custom(async (value, context: ValidationContext) => {
const {document, getClient, parent, path} = context
const client = getClient({apiVersion: '2024-01-01'})
const exists = await client.fetch('count(*[slug.current == $slug]) > 0', {
slug: value,
})
if (exists) return 'Slug must be unique'
return true
})
Validation contextThe document being validated
Parent value in the document tree
Function to get a Sanity client
Example: Custom Validation
import {type Rule} from 'sanity'
export default {
name: 'article',
type: 'document',
fields: [
{
name: 'slug',
type: 'slug',
validation: (Rule: Rule) => [
Rule.required(),
Rule.custom(async (slug, context) => {
if (!slug?.current) return true
const {document, getClient} = context
const client = getClient({apiVersion: '2024-01-01'})
const exists = await client.fetch(
'count(*[_type == "article" && slug.current == $slug && _id != $id]) > 0',
{slug: slug.current, id: document._id}
)
return exists ? 'Slug must be unique' : true
}),
],
},
{
name: 'publishDate',
type: 'datetime',
validation: (Rule: Rule) =>
Rule.min(new Date().toISOString())
.error('Publish date cannot be in the past'),
},
{
name: 'tags',
type: 'array',
of: [{type: 'string'}],
validation: (Rule: Rule) =>
Rule.min(1).max(10).unique(),
},
],
}