Sanity URI validation not working with allowRelative and HTTPS scheme

7 replies
Last updated: May 17, 2021
Hey-O, I am not able to get the URL validation working correctly. đŸ€Ż
validation: (Rule) =>
  Rule.required().uri({
    allowRelative: true, // Allow relative links
    relativeOnly: false, // Force only relative links
    scheme: ["https"], // Default is ["https", "http"]
  }),
},
I want to be able to provide links in the input field like “/home” || “/contact”, but seems allowRelative isn’t working or that specifying the scheme to https only is blocking that rule. Any suggestions?

I’ve tried validation on local and deployed environment
AI Update

I can see the issue! When you specify scheme: ["https"] in your URI validation, it conflicts with allowRelative: true. The scheme option tells Sanity to only accept URLs with the https protocol, which means relative URLs like "/home" or "/contact" will fail validation because they don't have a scheme at all.

Here's the fix - you need to remove the scheme option when you want to allow relative URLs:

validation: (Rule) =>
  Rule.required().uri({
    allowRelative: true, // Allow relative links
    relativeOnly: false, // Allow both relative AND absolute links
    // Don't specify scheme when allowing relative URLs
  }),

If you want to only accept relative URLs (like "/home", "/contact"), use:

validation: (Rule) =>
  Rule.required().uri({
    relativeOnly: true, // Only relative links allowed
  }),

If you want to accept either relative URLs or only HTTPS absolute URLs (but not HTTP), you'll need a custom validation function:

validation: (Rule) =>
  Rule.required().custom((value) => {
    if (!value) return true;
    
    // Allow relative URLs
    if (value.startsWith('/')) return true;
    
    // For absolute URLs, only allow HTTPS
    if (value.startsWith('https://')) return true;
    
    return 'Please use a relative URL (like /home) or an HTTPS URL';
  }),

The key takeaway: the scheme option in Rule.uri() is specifically for validating the protocol of absolute URLs. When you want to allow relative URLs, either omit the scheme option entirely or use custom validation logic if you need more complex rules combining relative paths with specific scheme requirements.

Show original thread
7 replies
would a custom validation work? i.e.
Rule.required().custom(
  (url) => (
    url[0] === '/' ||
    url.includes('https://')
  )
)
user P
Doesn’t seem like it does. I’ve done other custom validations with regex as well and wasn’t able to get a validation working. The example in my code block is what the default recommendation I could find anywhere suggest. I assume it is an issue with the handling of the options blocking each other.
Hi both, sorry about the confusion here: I believe at this point both
uri()
and
custom()
validation are required to get it to work. Could you try this snippet that was shared in the community a while ago?

Rule => Rule.required()
  .uri({
    allowRelative: true,
    scheme: ['https', 'http', 'mailto', 'tel'],
  })
  .custom(url => {
    if (!url) return 'URL is required';
    const isRelative = url.startsWith('/');
    const hasValidProtocol = ['https', 'mailto', 'tel'].some(protocol => url.startsWith(`${protocol}:`));
    const isValid = isRelative || hasValidProtocol;
    const msg = 'Must either start with "/", or with one of: "https://", "mailto:", or "tel:"';
     return isValid || msg;
   })
user M
I will give that a try
user M
This one did not work in my case. Appreciating the help, was this solution one that was working for you?
user A
user M
I was able to get it to work, simply just having https in the scheme option would not allow the validation to work when adding in relative links. If I didn’t have ‘http’ in the scheme it wouldn’t allow me to have relative links, so I had to add http back in. I know that we exclude http below in the custom rule, but seemed odd to have http in the scheme options at all just to have relative links enabled.
Should there just be a scheme that would do this for you, like if I only wanted https and relative then I would do this in the scheme options, relative would just allow anything to start with “/” you could also add a scheme that allows anchors which would be anything to start with “#” with page navigation and etc.

scheme: [ 'https', 'relative', 'anchor' ]
Good to hear you got it working! 🎉

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?