My team is running into a very confusing error where our 404 pages are throwing 500 errors, but only when the Languages.AlwaysStripLanguage configuration setting is set to "false". When we remove the following, the 404's work; navigating to ACME.com/qwerty delivers content from ACME.com/404.

    <setting name="Languages.AlwaysStripLanguage" value="false" />

Oddly enough, when we add it back in, they still continue working for a time... and then eventually begin throwing 500's again. A bit of digging also revealed that what seems to be happening is that when you navigate to ACME.com/qwerty the website properly pursues a 404, but then gets caught in an infinite loop trying to load ACME.com/en/404. At least, according to the Failed Request Tracing.

Unfortunately, we need the Languages.AlwaysStripLanguage setting in place. Primarily because our website needs to work as such:

  • (en-US Content) ACME.com
  • (en-CA Content) ACME.ca
  • (fr-CA Content) ACME.ca/fr

Our custom 404 logic came from the John Rappel article: https://www.geekhive.com/buzz/post/2017/07/a-complete-guide-to-configuring-friendly-error-pages-in-sitecore-part-1-404-pages/

Ultimately, the infinite loop seems to be happening because of this line from the Set404StatusCode class:

HttpContext.Current.Response.StatusCode = (int)HttpStatusCode.NotFound;

Where during this situation (and only this situation) this line throws an error stating that the status code can't be changed after it has been set.

Has anyone else run into problems running John Rappel's 404 code alongside setting Languages.AlwaysStripLanguage to false?

Am I missing something very obvious? Is there anything else I can provide to be more helpful?

  • 1
    Did you implement the Nuget package or raw code? If you used the Nuget package it’s likely best to revert to using the raw code to let you debug properly. I will push a change to the code base is it’s a true bug. Please let me know.
    – jrap
    May 2, 2019 at 23:53
  • Hey @jrap, when this was originally put together, it was done so using the raw code. I tried stripping everything out and adding it to our SitecoreExtensions Foundation, then to our Project via Nuget. Unfortunately, both approaches had their own problem. Since the Nuget package didn't seem to play nice with our Helix implementation, I'm currently going through and re-implementing the raw code solution again step by step to see where we see the problem. Though, if you'd like more info on what failed on Nuget, let me know.
    – Villanite
    May 9, 2019 at 18:30
  • 404'ing things has largely been answered on this SSE post: sitecore.stackexchange.com/a/223/170 -- the safest thing to do is to replace the actual page item that's being served up and then just coast through the rest of the response pipeline. In that way, you avoid this problem all together. Your problem is exactly why I wrote that code in the answer. It's about the only truly correct way to do it in Sitecore that handles varying language configs and media items. May 10, 2019 at 18:17

1 Answer 1



Change this line of code in the CustomExecuteRequest:

var notFoundUrl = _baseLinkManager.GetItemUrl(notFoundItem);

To this:

var notFoundUrl = _baseLinkManager.GetItemUrl(notFoundItem, 
    new Sitecore.Links.UrlOptions
        AlwaysIncludeServerUrl = false

var extractedLanguageName = WebUtil.ExtractLanguageName(notFoundUrl);

if (!String.IsNullOrEmpty(extractedLanguageName)) 
    notFoundUrl = notFoundUrl.Replace($"/{extractedLanguageName}", "");

Long Version

Based on John Rappel's own advice, I did try to see if removing the 404 code completely at least let Sitecore behave as expected. Once the code was all removed, Sitecore did deliver its expected pages whenever requests to non-existing pages were made.

As I began putting the code back in, bit-by-bit, it didn't take long to spot the issue and where to fix it. As it turns out, my understanding of the issue was a bit off and the cause of the issue is actually occurring on the CustomExecuteRequest class.

The first issue I ran into was that the GetItemUrl(notFoundItem) code was actually returning a URL with the protocol attached: http://acme.com/en/404. This immediately began throwing errors because HttpContext.Current.Server.TransferRequest actually expects a relative path rather than a full path. By changing the code to match what's below, I was able to return /en/404 instead.

    new Sitecore.Links.UrlOptions
        AlwaysIncludeServerUrl = false

At this point, I began to see the infinite loop again. I quickly realized this infinite loop wasn't actually being caused by the line in the original question, but because the code was trying to redirect 404 traffic to /en/404, which didn't exist, so when it looked for /404 (as established via config changes), it found the /en/404 page all over again, trying to send traffic there, only to start the loop over again.

Because of this, I decided to simply use Sitecore to extract the language name from the url using this line of code:

var extractedLanguageName = WebUtil.ExtractLanguageName(notFoundUrl);

Now, with that in a variable, I can strip it from the url completely along with the preceding slash. Sure, I could leave the preceding slash in, but I felt that leaving the url to be //404 rather than /404 seemed sloppy. If anyone can think of a reason I shouldn't do this, I'd be very interested to read about it.

if (!String.IsNullOrEmpty(extractedLanguageName)) 
    notFoundUrl = notFoundUrl.Replace($"/{extractedLanguageName}", "");

Still being a novice to Sitecore, I have a feeling that maybe my approach (even if it works) might not be the best option. As such, if anyone has any reservations or comments, they're definitely very welcomed! For the time being, though, this works for all three of our languages, even preserving the /fr/ in the URL for the French Canadian 404's.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.