Filename validation for file type field in Sanity schema

4 repliesLast updated: Nov 29, 2025

Hello everyone! Has anyone ever done any filename validation in a schema with the "file" data type? I'll be periodically uploading newer versions of files and need to make sure I'm not adding the wrong file in any document.

export default {
    name'download',
    title'Download',
    type'document',
    fields: [
        {
            name'name',
            title'Name',
            type'string',
            validation: (Rule=&gtRule.required(),
        },
        {
            name'description',
            title'Description',
            type'string',
        },
        {
            name'filename',
            title'Filename',
            description'This will be the filename which the uploaded file must have.',
            type'string',
            validation: (Rule=&gtRule.required(),
        },
        {
            name'file',
            title'File',
            type'file',
            validation: (Rule=&gtRule.required(),
        },
        {
            name'active',
            title'Active',
            description'Is this download active?',
            type'boolean',
            initialValuetrue,
        },
    ],
}
If I try to do document level validation, I don't know how to get the original file name. Doing the following only gets me the hashed filename.

validation: (Rule) =>
    Rule.custom((doc) => {
        const matched = doc.filename === doc.file.asset._ref;
        return matched
            ? 'Uploaded filename does not match the expected filename.'
            : true
        return true;
    }),
AI Update

Good question! Yes, you can validate the filename by accessing the asset document's originalFilename property. The key issue you've identified is correct - doc.file.asset._ref only gives you the asset reference ID, not the actual filename.

Here's how to validate the filename using custom validation with the Sanity client:

Solution: Custom Validation with Asset Lookup

You can use custom validation that fetches the asset document to access the originalFilename:

export default {
    name: 'download',
    title: 'Download',
    type: 'document',
    fields: [
        {
            name: 'name',
            title: 'Name',
            type: 'string',
            validation: (Rule) => Rule.required(),
        },
        {
            name: 'filename',
            title: 'Filename',
            description: 'This will be the filename which the uploaded file must have.',
            type: 'string',
            validation: (Rule) => Rule.required(),
        },
        {
            name: 'file',
            title: 'File',
            type: 'file',
            validation: (Rule) => Rule.required().custom(async (value, context) => {
                if (!value?.asset?._ref) return true;
                
                const {getClient} = context;
                const client = getClient({apiVersion: '2024-01-01'});
                
                // Fetch the asset document to get originalFilename
                const asset = await client.fetch(
                    `*[_id == $assetId][0]{originalFilename}`,
                    {assetId: value.asset._ref}
                );
                
                // Get the expected filename from the parent document
                const expectedFilename = context.document?.filename;
                
                if (!expectedFilename) return true;
                
                if (asset?.originalFilename !== expectedFilename) {
                    return `Uploaded filename "${asset?.originalFilename}" does not match expected filename "${expectedFilename}"`;
                }
                
                return true;
            }),
        },
        {
            name: 'active',
            title: 'Active',
            description: 'Is this download active?',
            type: 'boolean',
            initialValue: true,
        },
    ],
}

How it works:

Important notes:

This approach ensures you're validating against the actual uploaded filename, preventing mismatches when periodically updating files!

Show original thread
4 replies

Was this answer helpful?

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.

Related contributions