7 common Next.js errors and how to solve them
Tags: nextjs, webdev
Published: 2023-08-23 18:49:49

**Written by [Kingsley Ubah](https://blog.logrocket.com/author/kingsleyubah/)✏️**

Next.js is presently one of the fastest-growing web frameworks in terms of adoption. In addition to features like [static site generation, server-side rendering](https://blog.logrocket.com/ssg-vs-ssr-in-next-js/), and file routing, the Next.js team continually [adds new features](https://blog.logrocket.com/new-features-in-next-js-11/) to make building highly optimized and performant web applications super easy. 

Despite the many benefits and features Next.js offers to developers, as with any framework, you might run into errors in your code during development. Next does a good job of logging helpful messages, but you might still find some errors hard to debug. 

This article explores the causes and solutions of some common errors in Next.js, including:

*   [Next.js hydration errors](#next-js-hydration-errors)
*   [Document or window object error](#document-window-object-error)
*   [Build failure due to webpack errors](#build-failure-webpack-errors)
*   [API and slug-related errors](#api-slug-related-errors)
*   [Error when importing modules](#error-importing-modules)
*   [CORS error — Debugging Next.js API routes](#cors-error-debugging-next-js-api-routes)
*   [Catching all errors in your Next.js app](#catching-all-errors-next-js-app)

Let’s jump right in.

## 1\. Next.js hydration errors <a name="next-js-hydration-errors">

One common error you’re likely to encounter in both Next and React apps is the hydration error. Hydration errors result from a mismatch between server- and client-rendered markup and differences in component states. 

Specifically, Next.js hydration errors arise when you wrap your components or HTML elements with an improper tag. A common example is when you have a `p` tag wrapping your divs, sections, or other elements. 

The exact error message you’ll get is:

```plaintext
Hydration failed because the initial UI does not match what was rendered on the server
```

To fix the error, you need to check the markup throughout your application and ensure that you’re not wrapping elements or custom components with improper tags. 

For example, the following component will result in a Next.js hydration error because we wrapped the `div` element inside the paragraph:

```javascript
import Image from 'next/image'

export const ErrorComponent = ()=>{
  return(
    <p>
      <div>Don't do this!</div>
      <Image src='/logo.jpg' alt='' width='40' height='40'/>
    </p>
  )
}
```

Rather, use the right “wrapper” elements — e.g. `div`, `section`, `main`, etc. — to wrap your content:

```javascript
export const CorrectComponent = ()=>{
  return(
    <div>
      <div>Do this instead</div>
      <Image src='/logo.jpg' alt='' width='40' height='40'/>
    </div>
  )
}
```

Keep in mind that some third-party components, [such as those from MUI](https://blog.logrocket.com/getting-started-with-mui-and-next-js/), may use the `<p>` tag as a top-level element. In such cases, you’ll need to wrap the component inside something semantic to avoid the error, like a `<div>` or `<section>`. 

Properly arranging your HTML will greatly reduce the likelihood of encountering the hydration error in your Next app, but it’s not the only cause. You can also encounter the error after importing and running certain packages, as we will explore in the next section.

## 2. Document or window object error <a name="document-window-object-error">

When you try to access the window object while the component is still mounting, Next.js will throw an error that the document or window is not defined. This error also occurs when you install and use a library that tries to access the window object before the component mounts. 

Suppose that you have a `home.js` file in your Next.js application. Attempting to access the local storage will result in the `window is not defined` error:

```javascript
const Home = () => {
  const saveSession = (event) => {
    window.sessionStorage.setItem("key", event.target.value)
  }   

  return (
      <div>
        <input
          type="text"
          id="message"
          name="message"
          onChange={saveSession}
          value={message}
        />
      </div>
  );
};

export default Home;
```

This is the same with third-party libraries. For example, let’s say you installed the `swiperjs` package and the library then tries to access the window object internally. Using `swiperjs` as demonstrated in the code below will also result in the same error:

```javascript
import { Swiper } from 'swiperjs'

const Home = () => {
  return (
    <>
      <Swiper
        spaceBetween={50}
        slidesPerView={3}
        navigation
        pagination={{ clickable: true }}  
       >
        // Slides go here
      </Swiper>
    </>
  );
};

export default Home;
```

This error occurs because `Swiper` is rendered before it can access the window object. To resolve this error, you need to execute the code that accesses the browser’s window object [inside the `useEffect()` Hook](https://blog.logrocket.com/useeffect-hook-complete-guide/). That way, the code only executes after the component has been mounted. 

Here’s how you’d rewrite the first example for it to work:

```javascript
const Home = () => {
  const saveSession = (event) => {
    useEffect(() => {
      window.sessionStorage.setItem("key", event.target.value)
    })
  }    

  return (
      <div>
        <input
          type="text"
          id="message"
          name="message"
          onChange={saveSession}
          value={message}
        />
      </div>
  );
};

export default Home;
```

If you’re using a library that accesses the window object, you need to load the library only after the component has been mounted. For example, this is how you’d load `Swiper` to avoid the error:

```javascript
const Home = () => {
  const [domLoaded, setDomLoaded] = useState(false);

  useEffect(() => {
    setDomLoaded(true);
  }, []);

  return (
    <>
      {domLoaded && (
        <Swiper
          spaceBetween={50}
          // ...
        >
          <div>Test</div>
        </Swiper>
      )}
    </>
  );
};

export default Home;
```

## 3\. Build failure due to webpack errors <a name="build-failure-webpack-errors">

After running the `next build` command to build your Next.js application, you might get an error message stating that the build failed because of webpack errors:

```plaintext
Cannot read property 'asString' of undefined

> Build error occurred
Error: > Build failed because of webpack errors
```

Next.js v11 and newer [use webpack 5](https://blog.logrocket.com/new-features-in-webpack-5-2559755adf5e/) by default. However, this error only occurs with webpack 4. 

To resolve the issue, you need to enable webpack 5 in your Next.js application. You can do this by adding the following setting in `next.config.js`:

```javascript
module.exports = {
  // Add this:
  future: {
    webpack5: true,
  },
};
```

## 4\. API and slug-related errors <a name="api-slug-related-errors">

A large number of errors in Next.js are related to APIs and slugs. Next.js provides two APIs for data fetching — `getStaticPaths` and `getServerSideProps`. However, these functions can throw an error if not properly used. 

Here's an error you might often get with the `getStaticProps` API:

```plaintext
Error: getStaticPaths is required for dynamic SSG pages and is missing for '/productsPage/[slug]'
```

You get this error when you render a page on the server side with the SSG feature, but fail to define the `getStaticProps` function in the page’s component. 

This is because Next.js requires the `getStaticPaths` function to build server-side rendered or statically generated pages that use dynamic routes. So, the solution is simply to add a `getStaticPaths()` function to the page component for `/pageName/[slug]`. 

Let’s see an example. In a hypothetical ecommerce store, the `/pageName/[slug]` page could show the details of a particular product. 

In that case, you can use the `getStaticPaths` function to retrieve a list of all the available product slugs from a database, then return the list to be used for the `[slug]` parameter:

```javascript
export async function getStaticPaths() {
  const res = await fetch('http://localhost/path/to/products')
  const products = await res.json()
  const slugs = products.map(post => product.slug)

  return {
    paths: slugs.map((slug) => ({ params: { slug } })),
    fallback: false
  }
}
```

## 5\. Error when importing modules <a name="error-importing-modules">

When importing modules into your Next.js application, you might run into the `Module not found` error:

```plaintext
Module not found: Can't resolve 'fs'
```

This means that Next.js is unable to locate the module specified in the error message. If you’re using a local module, then you need to specify its correct path. But if it's an npm or Yarn module, the error usually occurs because the module isn’t available on the client side. 

One way to fix this issue is to ensure that all Node.js and server-related code is placed inside of the Next.js data-fetching APIs — `getServerSideProps`, `getStaticPaths`, or `getStaticProps`:

```javascript
export function Home({ fileInfo }) {
  return (
    <div>
      {/* page content */}
    </div>
  );
}

export default Home;

export async function getServerSideProps(context) {
  const util = require('util');
  const tring = util.format(1, 2, 3);

  return {
    props: {
      fileInfo,
    },
  };
}
```

If that fails to resolve the issue, then you might want to cross-check that the letter casing of the file you’re attempting to import is correct. Here’s an example:

```javascript
// components/MyComponent.js
export default function MyComponent() {
  return <h1>Hello</h1>
}
```

When importing the above component, you need to use the exact letter case of the filename:

```javascript
// pages/index.js

// This will not work
import MyComponent from '../components/Mycomponent'

// This will work
import MyComponent from '../components/MyComponent'
```

Note that incorrect letter casing will only lead to `Module not found` errors in case-sensitive environments.

## 6\. CORS error — Debugging Next.js API routes <a name="cors-error-debugging-next-js-api-routes">

The `/pages/api` directory is where you put all the files responsible for handling API requests, with the file name corresponding to the endpoint. Next.js then automatically maps these files to the `/api/*` URL, which you can access within the application via asynchronous API requests. 

Once you deploy your app to the internet, the app will exist on a different origin. As a result, attempting to access the API endpoint will result in a CORS error as shown below:

```plaintext
Access to fetch at 'http://example.com/api/test' from origin 'http://localhost:3000' has been blocked by CORS policy
```

To fix the CORS issue, you need to [use CORS to handle cross-origin requests](https://blog.logrocket.com/using-cors-next-js-handle-cross-origin-requests/). Start by installing `cors`:

```bash
npm install cors
# OR
yarn add cors
```

Once installation completes, you can import the library and use it to execute custom middleware just before the API’s response is received. Here’s an example where we set up the POST, GET, and HEAD methods for this endpoint:

```javascript
// pages/api/test.js

import Cors from "cors";

const cors = Cors({
  methods: ["POST", "GET", "HEAD"],
});

function middleware(req, res, fn) {
  return new Promise((resolve, reject) => {
    fn(req, res, (result) => {
      if (result instanceof Error) {
        return reject(result);
      }
      return resolve(result);
    });
  });
}

export default async function runMiddleware(req, res) {
  await middleware(req, res, cors);

  // Other API logic
  res.json({ result: result });
}
```

With this code, we can make all four types of API requests to a different origin successfully without encountering the CORS error.

## 7\. Catching all errors in your Next.js app <a name="catching-all-errors-next-js-app">

When creating your Next.js application, it’s important to catch all errors and make sure each of them is handled. The best way to do this is at the component level using the `try...catch` syntax. 

In the following example, if any error is encountered while fetching data from the API, we log the error, render the built-in error page, and pass in a 503 status code:

```javascript
import fetch from "isomorphic-fetch"
import Error from "next-error"

const Home extends React.Component {
  static async getInitialProps() {
    let products = [];

    try {
       const resp = fetch("https://my-store.com")
       products = await resp.json()
    } catch(err) {
       console.log(err)
    }

    return { products }
  }

  render () {
    const { products } = this.props

    if(products.length === 0) {
      return <Error statusCode={503} />
    }

    return (
     <div>
       {products.map((product) => {
         <h3 key={product.id}>{product.title}</h3> 
       })}
     </div>
    )
  }
}
```

To learn more about catching and resolving errors in Next.js, check out our articles on [testing and error handling patterns](https://blog.logrocket.com/testing-error-handling-patterns-next-js/) and [troubleshooting a Next app with ESLint](https://blog.logrocket.com/troubleshooting-next-js-app-eslint/).

## Conclusion

Next.js is growing in popularity and usage. But as with any other technology, an application built with Next.js isn’t safe from errors and issues. 

By reading up on common errors in Next.js, the causes of these errors, and their respective solutions — as we covered in this article — you can optimize your web app and ensure that it performs as expected.

---

## [LogRocket](https://lp.logrocket.com/blg/nextjs-signup): Full visibility into production Next.js apps

Debugging Next applications can be difficult, especially when users experience issues that are difficult to reproduce. If you’re interested in monitoring and tracking state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, [try LogRocket](https://lp.logrocket.com/blg/nextjs-signup).

[![LogRocket Signup](https://blog.logrocket.com/wp-content/uploads/2017/03/1d0cd-1s_rmyo6nbrasp-xtvbaxfg.png)](https://lp.logrocket.com/blg/nextjs-signup)

[LogRocket](https://lp.logrocket.com/blg/nextjs-signup) is like a DVR for web and mobile apps, recording literally everything that happens on your Next.js app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your Next.js apps — [start monitoring for free](https://lp.logrocket.com/blg/nextjs-signup).