Common Errors in Next.js and How to Resolve Them
Bugs are one of the most troubling aspects of software development; they appear out of nowhere and cause everything to stop working. Most of the time, they can be resolved quickly; however, others can be gruesome and take hours/days to fix.
Next.js is one of the most popular web development frameworks in the current world, and as a programming tool, it didn't escape the bug dilemma either.
To save you the back and forth, this article will explore some of the most common Next.js errors reported by developers on different platforms; we’ll cover why these bugs happen, as well as how to resolve them. Without further ado, let's get right into it.
Document/Window Object Error
One of the most common errors in Next.js is the document/window is not defined error. Why does it happen? This error typically appears when you or an installed package try to access the browser's window objects directly in a page component, and Next.js will throw this error because the window object is not yet available while a component is still mounting.
Say we have a sample index.js page in our Next.js application and try to access the browser localStorage like below; we’ll get the window is not defined error.
const Index = () => {
window.localStorage.foo = "bar";
return (
<>
# Hello world!
</>
);
};
export default Index;
How to resolve
There are different approaches to resolving this error, one straightforward option is to simply employ react’s useEffect() hook to execute the code block that requires the browser’s window object, so that the code is only executed when the page component had been mounted.
import { useEffect } from "react";
const Index = () => {
useEffect(() => {
window.localStorage.foo = "bar";
}, []);
return (
<>
# Welcome to my Blog!
</>
);
};
export default Index;
Another option is to convert the part of our code that requires the browser’s window to a standalone component and import it to our page component using Next.js dynamic import feature. Next’s dynamic import is a feature used to lazy-loading or dynamically load components on demand. However, it includes an additional ssr option that allows you to enable or disable server rendering when using it.
We can simply set the ssr value to false and will be able to load components or external packages that rely on the browser's window or document.
// components/SampleComponent.js
const SampleComponent = () => {
window.localStorage.foo = "bar";
return (
<>
# Welcome to my Blog!
</>
);
};
export default SampleComponent;
And dynamically load it in a page.
// pages/index.js
import dynamic from "next/dynamic";
const DynamicComponent = dynamic(
() => import("../components/SampleComponent"),
{
ssr: false,
}
);
const Index = () => {
return (
<>
# Hello world!
<DynamicComponent />
</>
);
};
export default Index;
Middleware Error
Middleware enables the execution of code prior to the completion of a request, and based on the incoming request, it modifies the response sent to the user by rewriting, redirecting, or even adding headers.
One error you could encounter when working with middleware in Next.js is
TypeError: Invalid URL
This error usually happens when you're using Next.js with a custom server, and you did not explicitly specify the server host URL in your configuration; additionally, if you are using a monorepo build system like Nx, you’d also likely experience this error as tools like this one creates a custom server for you behind the scene.
How to resolve
You can quickly fix this error by specifying the hostname in your server configuration file. If you are using nx, you can do this by modifying the serve options in your project configuration file (project.js). I.e., you modify this file to look like this.
"serve": {
"executor": "@nrwl/next:server",
"defaultConfiguration": "development",
"options": {
"buildTarget": "test-nx:build",
"dev": true,
"port": 4200,
"hostname": "localhost"
},
. . .
}
Middleware not triggered
In rare cases where your middleware code seems to not be triggered at all, this might have happened due to the incorrect placement of your middleware file.
How to resolve
In older versions of Next.js, you create your middleware file as _middleware.js
in the /pages directory. However, the latest versions of Next.js require that you save this file as middleware.js on the root folder, i.e. the same level as the /pages directory.
With this new change, your file structure should look like this.
.
├── . . .
├── pages
│ └── index.js
├── public
├── middleware.js
└── . . .
API/Slug Error
Next.js is shipped with the getStaticPaths
and getServerSideProps
API for data fetching; however, they occasionally throw errors when used incorrectly.
One of these errors, specifically with the getStaticProps API, is:
error - Error: getStaticPaths is required for dynamic SSG pages and is missing for '/pageName/[slug]'
This error occurs when a dynamic page is being rendered on the server-side using the Static Site Generation (SSG) feature in next.js, but the getStaticPaths() function is not defined in the page's component.
The getStaticPaths function is a required part of the Next.js API for building server-side rendered (SSR) or statically generated (SSG) pages that use dynamic routes.
How to resolve
To fix this error, you will need to add a getStaticPaths() function to the page component for /pageName/[slug].
For example, if the page at /pageName/[slug] is meant to display information about a blog post, the getStaticPaths function could fetch a list of all the available blog post slugs from a database and return them as the possible values for the [slug] parameter.
export async function getStaticPaths() {
// fetch list of available slugs from a database
const res = await fetch('http://localhost/path/to/blogs')
const posts = await res.json()
const slugs = posts.map(post => post.slug)
// return the possible values for the [slug] parameter
return {
paths: slugs.map((slug) => ({ params: { slug } })),
fallback: false
}
}
It is also worth mentioning that all the Next.js data fetching APIs can only be used inside page components, and will not work outside regular components.
Module Error
Another common error in Next.js is: Module not found: Can't resolve 'moduleName', e.g.
Module not found: Can't resolve 'fs'
This error usually occurs when you're importing a module that is not accessible by Next.js. Like with the case of the fs module, it is simply because the module is not available on the client side, and you or a third-party package had tried to access it.
How to resolve
You can resolve this error by making sure to keep all Node.js/server-related code inside of Next.js data fetching APIs — getServerSideProps, getStaticPaths, or getStaticProps.
export function Index({ fileInfo }) {
return (
{/* page content */}
);
}
export default Index;
export async function getServerSideProps(context) {
const fs = require('fs');
let fileInfo = fs.readFileSync('path/to/sample.txt');
return {
props: {
fileInfo,
},
};
}
In cases where the error had occurred because of a package you imported and not because you’re explicitly trying to access a Node.js module, you can modify your Next.js configuration file (next.config.js) to include an entry for webpack like this.
const nextConfig = {
reactStrictMode: true,
swcMinify: true,
webpack: (config, { isServer }) => {
if (!isServer) {
config.resolve.fallback = {
fs: false,
};
}
return config;
},
};
module.exports = nextConfig;
In this code, the isServer property of the options object is checked to determine if the current build is for the server-side or the client-side. If the build is not for the server-side (i.e. if isServer is false), then the fs module is added to the fallback list in the resolve section of the webpack configuration.
This means that when webpack encounters an import for the fs module, it will not attempt to resolve the import, and the fs module will not be bundled with the application. This allows the fs module to be loaded at runtime on the server-side, but not on the client-side.
If you're not using Node.js modules and still get the "module not found" error, ensure the module has been installed and imported properly. There may be a casing error, so double-check that.
Cors Error (Next API Routes)
Next.js allows users to create REST API endpoints by placing files with the desired endpoint names inside the /pages/api directory. These endpoints are then mapped to the /api/* URL and can be accessed from within the application by making asynchronous requests.
However, once your application has been deployed and you try to access the API endpoint from a different origin, you get the cors error like the one below.
Access to fetch at 'http://example.com/api/hello' from origin 'http://localhost:3001' has been blocked by CORS policy ...
How to resolve
We can fix this error by leveraging the popular cors package to enable cross-origin sharing before our API route sends its response. To do this, first, we have to install the cors package.
npm install cors
# OR
yarn add cors
After that, we can import this package to run custom middleware before the API route sends its response, enabling the preferred method for the specific endpoint; for example, we can enable the POST, GET, and HEAD methods for this endpoint.
// pages/api/hello.js
import Cors from "cors";
const cors = Cors({
methods: ["POST", "GET", "HEAD"],
});
function runMiddleware(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 handler(req, res) {
await runMiddleware(req, res, cors);
// Other API logic
res.json({ foo: "bar" });
}
You should stop experiencing cors errors once you have your API designed like this.
Next.js Error Monitoring with Sentry
Resolving errors during development writing tests is a crucial step in ensuring the quality and functionality of an application. However, it's not enough to simply fix errors as they arise during these stages. It's also essential to monitor the application's state and performance in production, where it will be used by actual users. This is because errors and performance issues not detected during development and testing may still occur in the production environment.
Sentry can help identify these issues by tracking your Next.js application's state and performance in real-time. You can configure your application to alert the development team when errors occur, allowing them to quickly address the issue and prevent it from impacting the user experience.
Additionally, Sentry provides valuable insights regarding your application's performance, such as response times and resource usage, which can help you optimize your application and improve its overall reliability.
Recap
Next.js is a popular and powerful framework for building web applications; however, like any technology, it is not immune to errors and issues. This article has covered some common errors in Next.js, what causes these errors, as well as how to resolve them.
We also emphasized the importance of using a monitoring tool to continually track the state of your application. To get started with monitoring your Next.js application check out this helpful guide.
FAQs
This error occurs when attempting to access browser-specific objects directly in Next.js page components. To resolve it, you can use React’s useEffect() hook to ensure code execution happens after component mounting or utilize the Next.js dynamic import feature with ssr set to false.
This error typically occurs when working with middleware in Next.js, particularly when the server host URL is not explicitly specified in the configuration.
This error is commonly encountered when using a custom server or monorepo build system like Nx.
You can resolve such errors by specifying the hostname in the server configuration file. For Nx projects, this involves modifying the project configuration file to include the hostname setting.
If your middleware code isn’t being triggered, it could be due to incorrect file placement. In older versions of Next.js (12.1 and lower), middleware files were named _middleware.js
within the /pages
directory, but in newer versions (12.2 and higher), they should be named middleware.js
in the root folder.
This error occurs when using the getStaticProps API for server-side rendering (SSG) but failing to define the getStaticPaths() function in the page’s component. It’s essential for building SSG pages with dynamic routes.
The “Module not found” error typically occurs when attempting to import a module, after already running npm install
, that’s not accessible by Next.js, especially server-side modules like fs. To resolve it, ensure server-related code is placed within Next.js data fetching APIs or configure webpack to handle such imports properly.
CORS errors arise when attempting to access Next.js API endpoints from different origins, especially after deployment. This issue can be resolved by incorporating the CORS package to enable cross-origin sharing in your API routes.
To handle CORS in Next.js API routes, install the CORS package and use it as custom middleware before sending the response from the API route. This enables cross-origin sharing for the specified HTTP methods.
Sentry is a performance monitoring tool that tracks an application’s state and performance in real time. It helps identify errors and performance issues in production environments, providing valuable insights for optimizing and improving the application’s reliability.