In this tutorial, you will learn how to apply graceful error handling within an Umbraco v9 (and above) website. Whenever you visit a website and you encounter a developer intended exception message, it does not give you great confidence about that brand. Adding some nice error handling whenever a 404 or 500 error is thrown will provide a much nicer user experience.

Luckily for you, setting all this up within Umbraco v9 is pretty simple and straightforward. Within this tutorial, you will learn how to set up a 404 page that will work for most websites. You will also learn how to use C# code in order to handle a 404 page using something called a ContentFinder. This can be handy when you are building a multi-language website and you need logic to determine which 404 page is the right one for the current site visitor. Your treat for making it to the end will be some best practice advice on how to architecture your 500 error pages and how to configure them.

If you want to master error handling within Umbraco v9 and above... this is the tutorial for you 🔥🔥🔥

Not Found Error Handling - 404

There are two ways of configuring a 404 in Umbraco, either in appsettings.json or using a content finder. Unless you have some gnarly requirement, go for the applicationsettings.json route. Creating the actual page that will be served as the 404 page can be done within the CMS. Either use an existing document type, like a content page, or create a new 404 specific type, the choice is yours. Remember, whenever you are creating a new document type, the alias name can not start with a number. This means the document-type alias 404 is not allowed. This is why most folks tend to pick NotFoundPage as the alias for their 404 specific document type 🤔.

After creating the page that you want to use as the 404 page within the CMS, you will need to make a note of its Id. You can access this information from the Info tab in the page editing view. When it comes to setting the page to use as the 404, you can reference it using either its Id, GUID, or its location in the tree using XPath.

Dealing With Not Found, 404 and 500 Errors Within Umbraco v9 1

I recommend that you forget about the XPath route. If you need to do something more complex, as you will shortly see, you can use a content finder instead. I personally find that referencing pages by Id is the best option. Using an Id makes it easier for developers to manually locate that page within the CMS, as you can use the Id to directly load a page within the backend:

You can add the Id within applicationsettings.json using the ContentId property:

One handy feature to be aware of with this JSON is that you can also define multiple 404 pages:

You might wonder why? Within a multi-language website, you might want to define a dedicated 404 page per language. Including the Culture with the Id will tell Umbraco in what circumstance it should load the 404 page 💥

In the very rare instance where you might need to trigger some complex logic in order to set which 404 should render, you can use a content finder. A content finder will be a less used tool within your toolbelt, however, it can be handy when you need to change what content gets returned for a specific Url.

You might be confused about the differences between a content finder and a routing rule. A routing rule will map a Url to a controller and an action. During this process, a look-up is made to the CMS in order to get some data out of the CMS and pass it into the controller. The content finder is the Umbraco mechanism that queries the database for a match. If a match is made, the code in the content finder can add the related page object into the request context for use within the controller.

Content Finder Usage

It is possible for you to create your own custom content finders to change how this lookup process works. Umbraco ships with two types of content finders. One is used for normal use. To define a normal content finder, create a class that implements the IContentFinder interface. The second type is triggered when no matches occur. This is the one we can use for 404 use. This type of content finder can be created by creating a new class that implements the IContentLastChanceFinder interface. The code to create this type of content finder is shown below:

In order for this code to trigger, it needs to be registered within a composer:

Doing these two things will give you a way to write C# code that determines which 404 page to return 😊

Exception Thrown Error Handling - 500

The other type of error that you will need to handle within your project are the errors triggered whenever an unhandled exception is thrown. Exceptions obviously indicate something has gone tits within the site. When a status of 500 (or within that range) is generated, you need a graceful way of dealing with it. I do not recommend using a Umbraco page to serve your 500 pages as it can cause big issues. Specifically, it can cause an infinite loop and a StackOverflow exception to be thrown.

Imagine your menu is throwing a 500 error on the homepage. The 500 page is CMS-based. The failed menu exception will result in Umbraco trying to load a new copy of the 500 page. Assuming the 500 page uses the same menu code as the page with the error, when the new request is being processed it will also throw a 500 error. This results in the handler trying to load the same 500 page again. This request will result in another error, which in turn throws another error. The process will repeat until the framework kills the process and throws a StackOverflow exception.

500 pages should only render when something has gone wrong. This is why you should always create a static 500 page, as status HTML will always display. To configure your application to use a static page, you need to add one line of config within the Startup.cs class:

The related static 500 page then needs to live here:


Within this HTML file, you are free to add whatever HTML you like. You now have a foolproof way of dealing with errors 🔥🔥🔥

You now know how to gracefully handle the main types of errors that a Umbraco site may encounter. Happy Coding 🤘