Validation not working on image type in Sanity document

8 replies
Last updated: May 30, 2022
Has anyone gotten the .required() validation to work on an image type? I didn’t realize until testing it today that no image added is not being flagged…
AI Update

I understand your frustration! This is actually a known issue with how Sanity's validation system works with image fields. The .required() validation on image fields can be tricky because of how image data is structured.

Here's what's happening: When you add .required() to an image field, it only validates that the image field object exists, not that it actually contains an asset reference. An image field in Sanity is an object with properties like asset, crop, and hotspot. So even without an uploaded image, the field can have an empty object {}, which passes the required validation.

The solution is to use custom validation that specifically checks for the asset reference:

defineField({
  name: 'image',
  type: 'image',
  validation: (rule) => rule.custom((value) => {
    if (!value?.asset) {
      return 'Image is required'
    }
    return true
  })
})

Or if you want to keep it more concise with chaining:

defineField({
  name: 'image',
  type: 'image',
  validation: (rule) => rule.required().custom((value) => {
    return value?.asset ? true : 'An image must be uploaded'
  })
})

The key is checking for value?.asset specifically, since that's the actual reference to the uploaded image in your Content Lake.

One important note from the validation documentation: validation only runs client-side in the Studio. If you're using API mutations directly, you'll need to implement server-side validation separately.

This same approach works for file fields too if you run into similar issues there!

It looks like it's working on my end. What does your code look like?
Hi
user M
thanks for responding! below is the ‘illustration’ object
export default {
  name: 'illustration',
  title: 'Illustration',
  type: 'image',
  fields: [
    {
      name: 'alt',
      type: 'string',
      title: 'Alt',
      options: {
        isHighlighted: true, // <-- make this field easily accessible
      },
    },

  ],

};
This is being used in our ‘soloGuidePage’ document for the fields ‘Tile Image’ and ‘Hero Image’. The validation is failing to provide ‘error’ when no image is selected.

export default {
  name: 'soloGuidePage',
  type: 'document',
  title: 'Solo Guide Page',
  icon: RiPagesLine,
  fieldsets: [
    {
      name: 'tile',
      title: 'Listing Tile Fields',
      options: {
        collapsible: true,
        collapsed: false,
      },
    },
    {
      name: 'hero',
      title: 'Hero',
      options: {
        collapsible: true,
        collapsed: false,
      },
    },
    {
      name: 'mainContent',
      title: 'Main Content',
      options: {
        collapsible: true,
        collapsed: false,
      },
    },
  ],
  fields: [
    {
      name: 'tileTitle',
      title: 'Tile Title',
      type: 'string',
      fieldset: 'tile',
      validation: (Rule) => [Rule.required().error('Field is required')],
    },
    {
      name: 'tileImage',
      title: 'Tile Image',
      type: 'illustration',
      fieldset: 'tile',
      validation: (Rule) => [Rule.required().error('Field is required')],
    },
    {
      name: 'tileText',
      title: 'Tile Text',
      type: 'text',
      fieldset: 'tile',
      validation: (Rule) => [Rule.required().error('Field is required')],
    },
    {
      name: 'h1',
      title: 'H1 Text',
      type: 'string',
      fieldset: 'hero',
      validation: (Rule) => [Rule.required().error('H1 Text is required')],
    },
    {
      name: 'heroSubtitle',
      title: 'Hero Subtitle Text',
      type: 'heroBlockPT',
      fieldset: 'hero',
    },
    {
      name: 'heroImage',
      title: 'Hero Image',
      type: 'illustration',
      fieldset: 'hero',
      validation: (Rule) => [Rule.required().error('Field is required')],
    },
    {
      name: 'toc',
      title: 'Table of Contents',
      type: 'array',
      of: [{ type: 'tocLink' }],
      description: 'The order should match the in content appearance.',
      fieldset: 'mainContent',
    },
    {
      name: 'guideBody',
      type: 'guideBodyPT',
      title: 'Guide Content Body',
      fieldset: 'mainContent',
      validation: (Rule) => [Rule.required().error('Field is required')],
    },
  ],
};
I see now! When you set the basic
Rule.required
, all that it's looking for is any value specified
tileImage
. If you just add something like
alt
, that requirement will be met. You'll need to set up a custom rule on either the
tileImage
or
illustration
field that checks for an asset. Like so:
{
      name: 'tileImage',
      type: 'illustration',
      validation: Rule =>
        Rule.custom(({ asset }) => {
          return asset ? true : 'An image is required';
        }),
    },
AHHHHHHHHH OMG! thank you ❤️
Haha, you're welcome!
Hi
user M
I've tried the same solution it works fine however at the beginning I get this error
any idea how to avoid this
and show "An image is required" only, even at the beginning

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?