Support Forums

How to deliver 404 within a section using role based access controls

Hi. So we’re using role based redirects and JWTs to limit access to a part of our website. Basically, if someone tries to access any url staring /this-gated-section, if they have the role the redirect says to allow them in and if not we show them a log in page.

/this-gated-section/* 200! Role=user

So the redirect rule for those with the right role looks something like that ^. This all works great. The only issue I have is if someone is in the gated section and tries to go to a url that doesn’t exist. If this happens anywhere else on the site they see our 404 page. But if, for example, someone with the right role tries to go to /this-gated-section/this-page-does-not-exist - they instead see the Netlify error page. Is there anyway around this if we have the redirect rule above? There are quite a lot of pages in the gated section, so it would be cumbersome to have to list them all individually in the redirects folder - but would creating something to do that be the only way to achieve this?

Hi @katcoutts,

This should do it:

/this-gated-section/* /404-page 404
/this-gated-section/* 200! Role=user

Hi @hrishikesh . I tried that but it breaks the gating. If I have no JWT token with the required role it starts to let me access any of the pages anyway. The 404 page works as we want it to, but gating is totally gone. So if I put the 404 page above the role based redirect, the gating breaks, and if I put it below, it never hits the 404 redirect and people see the Netlify one.

Would it be possible for you to share the website name or API ID so we can check what might be happening? If it needs to remain private, you can send it to my in a private message.

Thanks. Will message you.

Hi @katcoutts,

Based on your message, the staging one would be the right website to debug this, correct?

If yes, could you share the deploy link or the ID (just the string towards the end of the URL) after adding the 404 rules for the gated paths? Or if you’ve a previous deploy in which you had added the 404 rules, a link for that would work too.

Hi @katcoutts,

Thank you for taking time to explain your case in the private message. This does seem to be a shortcoming of the RBAC feature. I’m not sure if it’s broken, working as intended or if this was ever even considered, but at the moment, you’re right, you can’t have a custom 404 for logged in users. If you add the rule I suggested before the RBAC breaks altogether.

I’ll try to get an update regarding this as to if there’s any workaround for this.


The only workaround I could think was to individually list all the pages that exist in the gated section - but as I say, when I tried that, Netlify complained that the redirects were invalid. Is it not possible to do the gating type redirect on specific pages, rather than sections with the *?

Best wishes,


No, that should totally work. Mind sharing those redirects in the private message?

Hi @katcoutts,

I’d like to add that this is currently being investigated, however our redirects expert is out till Wednesday. We’d like to have his opinion, but if this is urgent, we can escalate it right away. Let us know how we should handle this.


I’m happy to wait to Wednesday - just good to know you’ve got it in hand.



Thank you for that. One of your developers took a look at this case and this is what they’ve to say:

It looks like this is a conceptual limitation of how the redirect engine works.

It boils down to:

  1. We iterate through all redirect rules until we find one which matches the path and the conditions (country, role etc)
  2. Once a rule is matched we check if it’s forced and do the file existence check if not

So, even if the file is not returning a 404, the next rule in line (the RBAC rule), is never triggered for the path.

We’re working to see if there’s a possible workaround you could use to get around this, but if not, the only option for you would be to add a 404.html in the root of the publish directory that would be site-wide, as in it won’t be a different page for only the gated route - it would be a common 404 page shared by the entire website.

There’s yet another workaround if you want the gated content to have its own 404 page different from the rest of the website.

You’d have to setup another website which would render only the admin content and place a 404.html in it. Then, in your main website, you can add a rule like this:

/gated-content/* https://another-website.netlify.app/:splat 200!

And setup the RBAC in that gated website.


Thanks for the update. So looking at point 2, my understanding is it’s the ! in the gating redirect rule that’s forcing it. If we removed that, would it mean we would match on that RBAC rule but, because there’s no !, we’d do a check that it exists?

Best wishes,


Basically yes, you’ve understood it correctly. Here’s a verbose explanation if you need.

The way forcing works is this:

You request a URL → Netlify loops through the redirect rules → It finds a match → Checks if the rule is forced →

  • If yes, then apply the rule as it is
  • If not, check if the source file exists
    • If the source file exists, don’t apply the redirect
    • If the source file doesn’t exist, apply the redirect

We need to force the gated rule because the rule needs to be applied regardless of the existence of the file. If we don’t force it, the rule won’t be applied as the file exists.

Thank you. That’s a really clear explanation and does leave us in a bit of a catch 22!
I’ll wait to hear back if anyone can think of a workaround that would allow us to still have a custom 404 in that section and also work on how we could make one single 404 page work for us if needed.

Sure thing @katcoutts. From our developers’ end we’ve those 2 workarounds, just to consolidate the together:

  1. Use a 404.html for the entire website OR
  2. Host the gated content on a different website with the custom 404 page as 404.html and gate that website using RBAC.

But, we’d follow along in case there is another pattern that some other customer could suggest that works better.