Handling errors while server side rendering your code in Nuxt.js

Today I was putting the final touches on a Nuxt.js application and my aim was to set up some nice looking error pages that are other than the default Nuxt ‘server error’. I ran into trouble because I had a few misconceptions about how Nuxt handles errors, and what features you get out of the box to help with this.

Naively, I thought that Nuxt would do everything for me

One of the reasons I love Nuxt is because of all of the features you get out of the box. But errors are one of those things, where no application can guess what you want to happen, when certain situations arise and it all starts going wrong.

It starts to get tricky even more when you are dealing with other technologies like Axios and its default interpretation of certain error codes, for better or for worse.

What types of errors am I trying to handle?

Firstly, I am writing an application that heavily uses Nuxt for the server side rendering capabilities it has. Every page I have must be able to be generated on the server to be as SEO friendly as any standard web page.

When writing lots of code that will all be executed on the server, you will likely run into the first kind of exception/error very quickly.

The Nuxt Server Error page, this is what you see when an unhandled exception is generated while the server side render operation is happening

When you get your data for your site from an API, using a library like Axios, depending on what you are retrieving you may end up with various response codes from your request. For instance, my API returns a 404 Not Found code if the specific query has returned no results. You are still getting a response, and a message telling you what has happened, but this will trigger an exception in Axios. If you do not handle this, you will get the error page as shown above. 404 is a fairly normal response code, but this one caught me out.

One important distinction to make is when you are running your application in npm run dev mode over a production npm run build mode, then you will see errors differently.

Nuxt error while in dev mode

So that pretty much sets the scene, when you are in SSR mode and you get an error, it all goes south pretty quickly.

So when this happens, what can do with the tools Nuxt gives you?

What got me confused

Most of everything you need is in the Nuxt Error View section of their documentation. This gets you started, but I still got confused around a few parts.

Thinking that Nuxt would show my error page for any unhandled exception

My first thought was that I was setting up a page that would replace the default Nuxt Server Error that I showed above. So I created the layout layouts/error.vue and populated it with the data snippets and template given in the Nuxt documentation. Rebuilt, I hit refresh on my page I was generating an error on....then nothing had changed.

What was wrong? Was my code wrong? Was something wrong with my Nuxt instance? Oh no, does Nuxt not actually handle errors well?

Well, what I had missed was this page about the Nuxt error handling method. Here it became clear that the Nuxt Error View is not about handling errors for you, but it is more about giving you a place you can direct your application to when things start going wrong.

eg. You must make an explicit call to the Nuxt error handler when YOU detect the error, likely in your .catch() block of the function or action you were running.

Ah ha!

Once I knew this, I started to test this out in my app. If I call the error method that is available in the context then I should see the result I am after.

Success, when I simulated a 404 on my API call, I was shown the error template that I had set up by calling the error method shown in the example above.

With this new success, I tried this out in another page I have in my app.

I redirected by calling the error() function, but it did not work…

This new error made me question what I had learned up until now. I had called the error function in the same way as the previous page, but now it wasn’t working. After a bit of digging around, I realised how the calls really work.

Ok, I think I have it now

There is a hierarchy that I had to figure out. The most important thing to know is that errors on the server take the most precedence over anything else. Not that they are more important, but they stop the execution of the Nuxt application. If you app encounters an exception, and you do not handle it, then it is going to stop. As a last resort, Nuxt can throw the Nuxt Server Error page. By this point, your Nuxt app has stopped executing. It has a static page it will return to the browser as part of the page request. There is no Nuxt magic at this point either so you cannot call for other resources or reference your Store or the error that caused this in the first place.

Everything finally came together for me when I realised that the Nuxt framework does not handle errors for you, but it allows you to handle knows error states yourself whether your app encounters an exception on the server or on the client.

This means that when ever you are running commands that can cause an exception, you must make sure you are going to catch and handle the exceptions. In my previous example where the I was catching my initial exception, I was actually missing the subsequent exceptions caused by the lack of the data I was expecting. Because of this, the Nuxt error() function was never able to fire properly in the Nuxt execution cycle, and the async nature of the error() function. Hence, I was still getting the Nuxt Server Error rather than my custom error page.

So what to learn from all of this?

After figuring out all of my trouble, I now know my priorities:

1. In the JS code, all possible exception must be handled. If you get an uncaught JavaScript error, then Nuxt will crash out of executing even if the exception occurs after you call error().

  • If your error can be silently handled, eg. no products returned from my API, then handle the 404 status code using a .catch() block in Axios. In my case with my API 404, I populate my product array with an empty array where my template knows what to show when the array length is zero.
  • This also mean any functions that can generate exceptions, like an Axios call, should be in a try/catch block.

2. Once the exception has been handled, if necessary I can display the Nuxt error() view to give the user some kinds of options for how to proceed. eg. Try again, or goto the home page

3. If there is an exception that I was not expecting or cannot handle, eg. the API is down and did not respond, then I can call error from the catch block in my nuxtServerInit function, or in any of the async function where the Nuxt context is present.

Now that we know how to deliver a custom error page when it is needed, we can concentrate on creating an experience that gets our users back on the path they need to be. Given we have the full power of Nuxt in the custom error view, there should be no shortage of helpful suggestions we can give our users.

BONUS: You can actually customise the default Nuxt Server Error page

As a side note, I found there is a way that you can actually customise the Nuxt Server Error page, this is not really a feasible method for handling most errors, but it is still worth a mention.

In your nuxt.config.js you can overwrite the template that is used to display this page. More info on replacing the contents of the error page here. Going one step further, you can overwrite this entire page using a method where you create a new file app/views/error.html in the root Nuxt application directory. Again, I would recommend against this as a 'solution' as by this point you are fully out of the Nuxt framework, and you are essentially coding a static HTML file. Can you try to render {{ this }} to see there is something kind of happening but it is as good as static ;)

For me, this approach does not work as I need to pull my main navigation contents from an API, and feed it into components. If I cannot do this (because I am no longer in the Nuxt framework), then it is not viable for my needs.

References

Change the Nuxt.js server error page

Custom Error Pages with nuxt.js

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store